Mercurial > repos > blastem
comparison nuklear_ui/nuklear.h @ 1474:c5c022c7aa54 nuklear_ui
Initial work on Nuklear-based UI
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 21 Nov 2017 19:07:43 -0800 |
parents | |
children | 5d10b8494b02 13abdc98379e |
comparison
equal
deleted
inserted
replaced
1473:152a60c6787e | 1474:c5c022c7aa54 |
---|---|
1 /* | |
2 Nuklear - 2.00.0 - public domain | |
3 no warranty implied; use at your own risk. | |
4 authored from 2015-2017 by Micha Mettke | |
5 | |
6 ABOUT: | |
7 This is a minimal state graphical user interface single header toolkit | |
8 written in ANSI C and licensed under public domain. | |
9 It was designed as a simple embeddable user interface for application and does | |
10 not have any dependencies, a default renderbackend or OS window and input handling | |
11 but instead provides a very modular library approach by using simple input state | |
12 for input and draw commands describing primitive shapes as output. | |
13 So instead of providing a layered library that tries to abstract over a number | |
14 of platform and render backends it only focuses on the actual UI. | |
15 | |
16 VALUES: | |
17 - Graphical user interface toolkit | |
18 - Single header library | |
19 - Written in C89 (a.k.a. ANSI C or ISO C90) | |
20 - Small codebase (~18kLOC) | |
21 - Focus on portability, efficiency and simplicity | |
22 - No dependencies (not even the standard library if not wanted) | |
23 - Fully skinnable and customizable | |
24 - Low memory footprint with total memory control if needed or wanted | |
25 - UTF-8 support | |
26 - No global or hidden state | |
27 - Customizable library modules (you can compile and use only what you need) | |
28 - Optional font baker and vertex buffer output | |
29 | |
30 USAGE: | |
31 This library is self contained in one single header file and can be used either | |
32 in header only mode or in implementation mode. The header only mode is used | |
33 by default when included and allows including this header in other headers | |
34 and does not contain the actual implementation. | |
35 | |
36 The implementation mode requires to define the preprocessor macro | |
37 NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.: | |
38 | |
39 #define NK_IMPLEMENTATION | |
40 #include "nuklear.h" | |
41 | |
42 Also optionally define the symbols listed in the section "OPTIONAL DEFINES" | |
43 below in header and implementation mode if you want to use additional functionality | |
44 or need more control over the library. | |
45 IMPORTANT: Every time you include "nuklear.h" you have to define the same flags. | |
46 This is very important not doing it either leads to compiler errors | |
47 or even worse stack corruptions. | |
48 | |
49 FEATURES: | |
50 - Absolutely no platform dependent code | |
51 - Memory management control ranging from/to | |
52 - Ease of use by allocating everything from standard library | |
53 - Control every byte of memory inside the library | |
54 - Font handling control ranging from/to | |
55 - Use your own font implementation for everything | |
56 - Use this libraries internal font baking and handling API | |
57 - Drawing output control ranging from/to | |
58 - Simple shapes for more high level APIs which already have drawing capabilities | |
59 - Hardware accessible anti-aliased vertex buffer output | |
60 - Customizable colors and properties ranging from/to | |
61 - Simple changes to color by filling a simple color table | |
62 - Complete control with ability to use skinning to decorate widgets | |
63 - Bendable UI library with widget ranging from/to | |
64 - Basic widgets like buttons, checkboxes, slider, ... | |
65 - Advanced widget like abstract comboboxes, contextual menus,... | |
66 - Compile time configuration to only compile what you need | |
67 - Subset which can be used if you do not want to link or use the standard library | |
68 - Can be easily modified to only update on user input instead of frame updates | |
69 | |
70 OPTIONAL DEFINES: | |
71 NK_PRIVATE | |
72 If defined declares all functions as static, so they can only be accessed | |
73 inside the file that contains the implementation | |
74 | |
75 NK_INCLUDE_FIXED_TYPES | |
76 If defined it will include header <stdint.h> for fixed sized types | |
77 otherwise nuklear tries to select the correct type. If that fails it will | |
78 throw a compiler error and you have to select the correct types yourself. | |
79 <!> If used needs to be defined for implementation and header <!> | |
80 | |
81 NK_INCLUDE_DEFAULT_ALLOCATOR | |
82 if defined it will include header <stdlib.h> and provide additional functions | |
83 to use this library without caring for memory allocation control and therefore | |
84 ease memory management. | |
85 <!> Adds the standard library with malloc and free so don't define if you | |
86 don't want to link to the standard library <!> | |
87 <!> If used needs to be defined for implementation and header <!> | |
88 | |
89 NK_INCLUDE_STANDARD_IO | |
90 if defined it will include header <stdio.h> and provide | |
91 additional functions depending on file loading. | |
92 <!> Adds the standard library with fopen, fclose,... so don't define this | |
93 if you don't want to link to the standard library <!> | |
94 <!> If used needs to be defined for implementation and header <!> | |
95 | |
96 NK_INCLUDE_STANDARD_VARARGS | |
97 if defined it will include header <stdarg.h> and provide | |
98 additional functions depending on variable arguments | |
99 <!> Adds the standard library with va_list and so don't define this if | |
100 you don't want to link to the standard library<!> | |
101 <!> If used needs to be defined for implementation and header <!> | |
102 | |
103 NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
104 Defining this adds a vertex draw command list backend to this | |
105 library, which allows you to convert queue commands into vertex draw commands. | |
106 This is mainly if you need a hardware accessible format for OpenGL, DirectX, | |
107 Vulkan, Metal,... | |
108 <!> If used needs to be defined for implementation and header <!> | |
109 | |
110 NK_INCLUDE_FONT_BAKING | |
111 Defining this adds `stb_truetype` and `stb_rect_pack` implementation | |
112 to this library and provides font baking and rendering. | |
113 If you already have font handling or do not want to use this font handler | |
114 you don't have to define it. | |
115 <!> If used needs to be defined for implementation and header <!> | |
116 | |
117 NK_INCLUDE_DEFAULT_FONT | |
118 Defining this adds the default font: ProggyClean.ttf into this library | |
119 which can be loaded into a font atlas and allows using this library without | |
120 having a truetype font | |
121 <!> Enabling this adds ~12kb to global stack memory <!> | |
122 <!> If used needs to be defined for implementation and header <!> | |
123 | |
124 NK_INCLUDE_COMMAND_USERDATA | |
125 Defining this adds a userdata pointer into each command. Can be useful for | |
126 example if you want to provide custom shaders depending on the used widget. | |
127 Can be combined with the style structures. | |
128 <!> If used needs to be defined for implementation and header <!> | |
129 | |
130 NK_BUTTON_TRIGGER_ON_RELEASE | |
131 Different platforms require button clicks occurring either on buttons being | |
132 pressed (up to down) or released (down to up). | |
133 By default this library will react on buttons being pressed, but if you | |
134 define this it will only trigger if a button is released. | |
135 <!> If used it is only required to be defined for the implementation part <!> | |
136 | |
137 NK_ZERO_COMMAND_MEMORY | |
138 Defining this will zero out memory for each drawing command added to a | |
139 drawing queue (inside nk_command_buffer_push). Zeroing command memory | |
140 is very useful for fast checking (using memcmp) if command buffers are | |
141 equal and avoid drawing frames when nothing on screen has changed since | |
142 previous frame. | |
143 | |
144 NK_ASSERT | |
145 If you don't define this, nuklear will use <assert.h> with assert(). | |
146 <!> Adds the standard library so define to nothing of not wanted <!> | |
147 <!> If used needs to be defined for implementation and header <!> | |
148 | |
149 NK_BUFFER_DEFAULT_INITIAL_SIZE | |
150 Initial buffer size allocated by all buffers while using the default allocator | |
151 functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't | |
152 want to allocate the default 4k memory then redefine it. | |
153 <!> If used needs to be defined for implementation and header <!> | |
154 | |
155 NK_MAX_NUMBER_BUFFER | |
156 Maximum buffer size for the conversion buffer between float and string | |
157 Under normal circumstances this should be more than sufficient. | |
158 <!> If used needs to be defined for implementation and header <!> | |
159 | |
160 NK_INPUT_MAX | |
161 Defines the max number of bytes which can be added as text input in one frame. | |
162 Under normal circumstances this should be more than sufficient. | |
163 <!> If used it is only required to be defined for the implementation part <!> | |
164 | |
165 NK_MEMSET | |
166 You can define this to 'memset' or your own memset implementation | |
167 replacement. If not nuklear will use its own version. | |
168 <!> If used it is only required to be defined for the implementation part <!> | |
169 | |
170 NK_MEMCPY | |
171 You can define this to 'memcpy' or your own memcpy implementation | |
172 replacement. If not nuklear will use its own version. | |
173 <!> If used it is only required to be defined for the implementation part <!> | |
174 | |
175 NK_SQRT | |
176 You can define this to 'sqrt' or your own sqrt implementation | |
177 replacement. If not nuklear will use its own slow and not highly | |
178 accurate version. | |
179 <!> If used it is only required to be defined for the implementation part <!> | |
180 | |
181 NK_SIN | |
182 You can define this to 'sinf' or your own sine implementation | |
183 replacement. If not nuklear will use its own approximation implementation. | |
184 <!> If used it is only required to be defined for the implementation part <!> | |
185 | |
186 NK_COS | |
187 You can define this to 'cosf' or your own cosine implementation | |
188 replacement. If not nuklear will use its own approximation implementation. | |
189 <!> If used it is only required to be defined for the implementation part <!> | |
190 | |
191 NK_STRTOD | |
192 You can define this to `strtod` or your own string to double conversion | |
193 implementation replacement. If not defined nuklear will use its own | |
194 imprecise and possibly unsafe version (does not handle nan or infinity!). | |
195 <!> If used it is only required to be defined for the implementation part <!> | |
196 | |
197 NK_DTOA | |
198 You can define this to `dtoa` or your own double to string conversion | |
199 implementation replacement. If not defined nuklear will use its own | |
200 imprecise and possibly unsafe version (does not handle nan or infinity!). | |
201 <!> If used it is only required to be defined for the implementation part <!> | |
202 | |
203 NK_VSNPRINTF | |
204 If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO` | |
205 and want to be safe define this to `vsnprintf` on compilers supporting | |
206 later versions of C or C++. By default nuklear will check for your stdlib version | |
207 in C as well as compiler version in C++. if `vsnprintf` is available | |
208 it will define it to `vsnprintf` directly. If not defined and if you have | |
209 older versions of C or C++ it will be defined to `vsprintf` which is unsafe. | |
210 <!> If used it is only required to be defined for the implementation part <!> | |
211 | |
212 NK_BYTE | |
213 NK_INT16 | |
214 NK_UINT16 | |
215 NK_INT32 | |
216 NK_UINT32 | |
217 NK_SIZE_TYPE | |
218 NK_POINTER_TYPE | |
219 If you compile without NK_USE_FIXED_TYPE then a number of standard types | |
220 will be selected and compile time validated. If they are incorrect you can | |
221 define the correct types by overloading these type defines. | |
222 | |
223 CREDITS: | |
224 Developed by Micha Mettke and every direct or indirect contributor. | |
225 | |
226 Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain) | |
227 Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). | |
228 | |
229 Big thank you to Omar Cornut (ocornut@github) for his imgui library and | |
230 giving me the inspiration for this library, Casey Muratori for handmade hero | |
231 and his original immediate mode graphical user interface idea and Sean | |
232 Barret for his amazing single header libraries which restored my faith | |
233 in libraries and brought me to create some of my own. | |
234 | |
235 LICENSE: | |
236 This software is dual-licensed to the public domain and under the following | |
237 license: you are granted a perpetual, irrevocable license to copy, modify, | |
238 publish and distribute this file as you see fit. | |
239 */ | |
240 #ifndef NK_NUKLEAR_H_ | |
241 #define NK_NUKLEAR_H_ | |
242 | |
243 #ifdef __cplusplus | |
244 extern "C" { | |
245 #endif | |
246 /* | |
247 * ============================================================== | |
248 * | |
249 * CONSTANTS | |
250 * | |
251 * =============================================================== | |
252 */ | |
253 #define NK_UNDEFINED (-1.0f) | |
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */ | |
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/ | |
256 #ifndef NK_INPUT_MAX | |
257 #define NK_INPUT_MAX 16 | |
258 #endif | |
259 #ifndef NK_MAX_NUMBER_BUFFER | |
260 #define NK_MAX_NUMBER_BUFFER 64 | |
261 #endif | |
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT | |
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f | |
264 #endif | |
265 /* | |
266 * ============================================================== | |
267 * | |
268 * HELPER | |
269 * | |
270 * =============================================================== | |
271 */ | |
272 #ifndef NK_API | |
273 #ifdef NK_PRIVATE | |
274 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L)) | |
275 #define NK_API static inline | |
276 #elif defined(__cplusplus) | |
277 #define NK_API static inline | |
278 #else | |
279 #define NK_API static | |
280 #endif | |
281 #else | |
282 #define NK_API extern | |
283 #endif | |
284 #endif | |
285 | |
286 #define NK_INTERN static | |
287 #define NK_STORAGE static | |
288 #define NK_GLOBAL static | |
289 | |
290 #define NK_FLAG(x) (1 << (x)) | |
291 #define NK_STRINGIFY(x) #x | |
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x) | |
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 | |
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2) | |
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2) | |
296 | |
297 #ifdef _MSC_VER | |
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__) | |
299 #else | |
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__) | |
301 #endif | |
302 | |
303 #ifndef NK_STATIC_ASSERT | |
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1] | |
305 #endif | |
306 | |
307 #ifndef NK_FILE_LINE | |
308 #ifdef _MSC_VER | |
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__) | |
310 #else | |
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__) | |
312 #endif | |
313 #endif | |
314 | |
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b)) | |
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a)) | |
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) | |
318 /* | |
319 * =============================================================== | |
320 * | |
321 * BASIC | |
322 * | |
323 * =============================================================== | |
324 */ | |
325 #ifdef NK_INCLUDE_FIXED_TYPES | |
326 #include <stdint.h> | |
327 #define NK_INT8 int8_t | |
328 #define NK_UINT8 uint8_t | |
329 #define NK_INT16 int16_t | |
330 #define NK_UINT16 uint16_t | |
331 #define NK_INT32 int32_t | |
332 #define NK_UINT32 uint32_t | |
333 #define NK_SIZE_TYPE uintptr_t | |
334 #define NK_POINTER_TYPE uintptr_t | |
335 #else | |
336 #ifndef NK_INT8 | |
337 #define NK_INT8 char | |
338 #endif | |
339 #ifndef NK_UINT8 | |
340 #define NK_UINT8 unsigned char | |
341 #endif | |
342 #ifndef NK_INT16 | |
343 #define NK_INT16 signed short | |
344 #endif | |
345 #ifndef NK_UINT16 | |
346 #define NK_UINT16 unsigned short | |
347 #endif | |
348 #ifndef NK_INT32 | |
349 #if defined(_MSC_VER) | |
350 #define NK_INT32 __int32 | |
351 #else | |
352 #define NK_INT32 signed int | |
353 #endif | |
354 #endif | |
355 #ifndef NK_UINT32 | |
356 #if defined(_MSC_VER) | |
357 #define NK_UINT32 unsigned __int32 | |
358 #else | |
359 #define NK_UINT32 unsigned int | |
360 #endif | |
361 #endif | |
362 #ifndef NK_SIZE_TYPE | |
363 #if defined(_WIN64) && defined(_MSC_VER) | |
364 #define NK_SIZE_TYPE unsigned __int64 | |
365 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) | |
366 #define NK_SIZE_TYPE unsigned __int32 | |
367 #elif defined(__GNUC__) || defined(__clang__) | |
368 #if defined(__x86_64__) || defined(__ppc64__) | |
369 #define NK_SIZE_TYPE unsigned long | |
370 #else | |
371 #define NK_SIZE_TYPE unsigned int | |
372 #endif | |
373 #else | |
374 #define NK_SIZE_TYPE unsigned long | |
375 #endif | |
376 #endif | |
377 #ifndef NK_POINTER_TYPE | |
378 #if defined(_WIN64) && defined(_MSC_VER) | |
379 #define NK_POINTER_TYPE unsigned __int64 | |
380 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) | |
381 #define NK_POINTER_TYPE unsigned __int32 | |
382 #elif defined(__GNUC__) || defined(__clang__) | |
383 #if defined(__x86_64__) || defined(__ppc64__) | |
384 #define NK_POINTER_TYPE unsigned long | |
385 #else | |
386 #define NK_POINTER_TYPE unsigned int | |
387 #endif | |
388 #else | |
389 #define NK_POINTER_TYPE unsigned long | |
390 #endif | |
391 #endif | |
392 #endif | |
393 | |
394 typedef NK_INT8 nk_char; | |
395 typedef NK_UINT8 nk_uchar; | |
396 typedef NK_UINT8 nk_byte; | |
397 typedef NK_INT16 nk_short; | |
398 typedef NK_UINT16 nk_ushort; | |
399 typedef NK_INT32 nk_int; | |
400 typedef NK_UINT32 nk_uint; | |
401 typedef NK_SIZE_TYPE nk_size; | |
402 typedef NK_POINTER_TYPE nk_ptr; | |
403 | |
404 typedef nk_uint nk_hash; | |
405 typedef nk_uint nk_flags; | |
406 typedef nk_uint nk_rune; | |
407 | |
408 /* Make sure correct type size: | |
409 * This will fire with a negative subscript error if the type sizes | |
410 * are set incorrectly by the compiler, and compile out if not */ | |
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2); | |
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); | |
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); | |
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4); | |
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); | |
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); | |
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); | |
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); | |
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); | |
420 | |
421 /* ============================================================================ | |
422 * | |
423 * API | |
424 * | |
425 * =========================================================================== */ | |
426 struct nk_buffer; | |
427 struct nk_allocator; | |
428 struct nk_command_buffer; | |
429 struct nk_draw_command; | |
430 struct nk_convert_config; | |
431 struct nk_style_item; | |
432 struct nk_text_edit; | |
433 struct nk_draw_list; | |
434 struct nk_user_font; | |
435 struct nk_panel; | |
436 struct nk_context; | |
437 struct nk_draw_vertex_layout_element; | |
438 struct nk_style_button; | |
439 struct nk_style_toggle; | |
440 struct nk_style_selectable; | |
441 struct nk_style_slide; | |
442 struct nk_style_progress; | |
443 struct nk_style_scrollbar; | |
444 struct nk_style_edit; | |
445 struct nk_style_property; | |
446 struct nk_style_chart; | |
447 struct nk_style_combo; | |
448 struct nk_style_tab; | |
449 struct nk_style_window_header; | |
450 struct nk_style_window; | |
451 | |
452 enum {nk_false, nk_true}; | |
453 struct nk_color {nk_byte r,g,b,a;}; | |
454 struct nk_colorf {float r,g,b,a;}; | |
455 struct nk_vec2 {float x,y;}; | |
456 struct nk_vec2i {short x, y;}; | |
457 struct nk_rect {float x,y,w,h;}; | |
458 struct nk_recti {short x,y,w,h;}; | |
459 typedef char nk_glyph[NK_UTF_SIZE]; | |
460 typedef union {void *ptr; int id;} nk_handle; | |
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];}; | |
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; | |
463 struct nk_scroll {nk_uint x, y;}; | |
464 | |
465 enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; | |
466 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; | |
467 enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; | |
468 enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; | |
469 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; | |
470 enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; | |
471 enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; | |
472 enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; | |
473 enum nk_color_format {NK_RGB, NK_RGBA}; | |
474 enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; | |
475 enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; | |
476 enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; | |
477 | |
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); | |
479 typedef void (*nk_plugin_free)(nk_handle, void *old); | |
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); | |
481 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); | |
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); | |
483 | |
484 struct nk_allocator { | |
485 nk_handle userdata; | |
486 nk_plugin_alloc alloc; | |
487 nk_plugin_free free; | |
488 }; | |
489 enum nk_symbol_type { | |
490 NK_SYMBOL_NONE, | |
491 NK_SYMBOL_X, | |
492 NK_SYMBOL_UNDERSCORE, | |
493 NK_SYMBOL_CIRCLE_SOLID, | |
494 NK_SYMBOL_CIRCLE_OUTLINE, | |
495 NK_SYMBOL_RECT_SOLID, | |
496 NK_SYMBOL_RECT_OUTLINE, | |
497 NK_SYMBOL_TRIANGLE_UP, | |
498 NK_SYMBOL_TRIANGLE_DOWN, | |
499 NK_SYMBOL_TRIANGLE_LEFT, | |
500 NK_SYMBOL_TRIANGLE_RIGHT, | |
501 NK_SYMBOL_PLUS, | |
502 NK_SYMBOL_MINUS, | |
503 NK_SYMBOL_MAX | |
504 }; | |
505 /* ============================================================================= | |
506 * | |
507 * CONTEXT | |
508 * | |
509 * =============================================================================*/ | |
510 /* Contexts are the main entry point and the majestro of nuklear and contain all required state. | |
511 * They are used for window, memory, input, style, stack, commands and time management and need | |
512 * to be passed into all nuklear GUI specific functions. | |
513 * | |
514 * Usage | |
515 * ------------------- | |
516 * To use a context it first has to be initialized which can be achieved by calling | |
517 * one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`. | |
518 * Each takes in a font handle and a specific way of handling memory. Memory control | |
519 * hereby ranges from standard library to just specifying a fixed sized block of memory | |
520 * which nuklear has to manage itself from. | |
521 * | |
522 * struct nk_context ctx; | |
523 * nk_init_xxx(&ctx, ...); | |
524 * while (1) { | |
525 * [...] | |
526 * nk_clear(&ctx); | |
527 * } | |
528 * nk_free(&ctx); | |
529 * | |
530 * Reference | |
531 * ------------------- | |
532 * nk_init_default - Initializes context with standard library memory allocation (malloc,free) | |
533 * nk_init_fixed - Initializes context from single fixed size memory block | |
534 * nk_init - Initializes context with memory allocator callbacks for alloc and free | |
535 * nk_init_custom - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations | |
536 * nk_clear - Called at the end of the frame to reset and prepare the context for the next frame | |
537 * nk_free - Shutdown and free all memory allocated inside the context | |
538 * nk_set_user_data - Utility function to pass user data to draw command | |
539 */ | |
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
541 /* nk_init_default - Initializes a `nk_context` struct with a default standard library allocator. | |
542 * Should be used if you don't want to be bothered with memory management in nuklear. | |
543 * Parameters: | |
544 * @ctx must point to an either stack or heap allocated `nk_context` struct | |
545 * @font must point to a previously initialized font handle for more info look at font documentation | |
546 * Return values: | |
547 * true(1) on success | |
548 * false(0) on failure */ | |
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*); | |
550 #endif | |
551 /* nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block | |
552 * Should be used if you want complete control over nuklear's memory management. | |
553 * Especially recommended for system with little memory or systems with virtual memory. | |
554 * For the later case you can just allocate for example 16MB of virtual memory | |
555 * and only the required amount of memory will actually be committed. | |
556 * IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands` | |
557 * Parameters: | |
558 * @ctx must point to an either stack or heap allocated `nk_context` struct | |
559 * @memory must point to a previously allocated memory block | |
560 * @size must contain the total size of @memory | |
561 * @font must point to a previously initialized font handle for more info look at font documentation | |
562 * Return values: | |
563 * true(1) on success | |
564 * false(0) on failure */ | |
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); | |
566 /* nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate | |
567 * memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation | |
568 * interface to nuklear. Can be useful for cases like monitoring memory consumption. | |
569 * Parameters: | |
570 * @ctx must point to an either stack or heap allocated `nk_context` struct | |
571 * @alloc must point to a previously allocated memory allocator | |
572 * @font must point to a previously initialized font handle for more info look at font documentation | |
573 * Return values: | |
574 * true(1) on success | |
575 * false(0) on failure */ | |
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); | |
577 /* nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing | |
578 * buffers. The first buffer is for allocating draw commands while the second buffer is | |
579 * used for allocating windows, panels and state tables. | |
580 * Parameters: | |
581 * @ctx must point to an either stack or heap allocated `nk_context` struct | |
582 * @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into | |
583 * @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables | |
584 * @font must point to a previously initialized font handle for more info look at font documentation | |
585 * Return values: | |
586 * true(1) on success | |
587 * false(0) on failure */ | |
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); | |
589 /* nk_clear - Resets the context state at the end of the frame. This includes mostly | |
590 * garbage collector tasks like removing windows or table not called and therefore | |
591 * used anymore. | |
592 * Parameters: | |
593 * @ctx must point to a previously initialized `nk_context` struct */ | |
594 NK_API void nk_clear(struct nk_context*); | |
595 /* nk_free - Frees all memory allocated by nuklear. Not needed if context was | |
596 * initialized with `nk_init_fixed`. | |
597 * Parameters: | |
598 * @ctx must point to a previously initialized `nk_context` struct */ | |
599 NK_API void nk_free(struct nk_context*); | |
600 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
601 /* nk_set_user_data - Sets the currently passed userdata passed down into each draw command. | |
602 * Parameters: | |
603 * @ctx must point to a previously initialized `nk_context` struct | |
604 * @data handle with either pointer or index to be passed into every draw commands */ | |
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); | |
606 #endif | |
607 /* ============================================================================= | |
608 * | |
609 * INPUT | |
610 * | |
611 * =============================================================================*/ | |
612 /* The input API is responsible for holding the current input state composed of | |
613 * mouse, key and text input states. | |
614 * It is worth noting that no direct os or window handling is done in nuklear. | |
615 * Instead all input state has to be provided by platform specific code. This in one hand | |
616 * expects more work from the user and complicates usage but on the other hand | |
617 * provides simple abstraction over a big number of platforms, libraries and other | |
618 * already provided functionality. | |
619 * | |
620 * Usage | |
621 * ------------------- | |
622 * Input state needs to be provided to nuklear by first calling `nk_input_begin` | |
623 * which resets internal state like delta mouse position and button transistions. | |
624 * After `nk_input_begin` all current input state needs to be provided. This includes | |
625 * mouse motion, button and key pressed and released, text input and scrolling. | |
626 * Both event- or state-based input handling are supported by this API | |
627 * and should work without problems. Finally after all input state has been | |
628 * mirrored `nk_input_end` needs to be called to finish input process. | |
629 * | |
630 * struct nk_context ctx; | |
631 * nk_init_xxx(&ctx, ...); | |
632 * while (1) { | |
633 * Event evt; | |
634 * nk_input_begin(&ctx); | |
635 * while (GetEvent(&evt)) { | |
636 * if (evt.type == MOUSE_MOVE) | |
637 * nk_input_motion(&ctx, evt.motion.x, evt.motion.y); | |
638 * else if (evt.type == ...) { | |
639 * ... | |
640 * } | |
641 * } | |
642 * nk_input_end(&ctx); | |
643 * [...] | |
644 * nk_clear(&ctx); | |
645 * } | |
646 * nk_free(&ctx); | |
647 * | |
648 * Reference | |
649 * ------------------- | |
650 * nk_input_begin - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls | |
651 * nk_input_motion - Mirrors mouse cursor position | |
652 * nk_input_key - Mirrors key state with either pressed or released | |
653 * nk_input_button - Mirrors mouse button state with either pressed or released | |
654 * nk_input_scroll - Mirrors mouse scroll values | |
655 * nk_input_char - Adds a single ASCII text character into an internal text buffer | |
656 * nk_input_glyph - Adds a single multi-byte UTF-8 character into an internal text buffer | |
657 * nk_input_unicode - Adds a single unicode rune into an internal text buffer | |
658 * 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 | |
659 */ | |
660 enum nk_keys { | |
661 NK_KEY_NONE, | |
662 NK_KEY_SHIFT, | |
663 NK_KEY_CTRL, | |
664 NK_KEY_DEL, | |
665 NK_KEY_ENTER, | |
666 NK_KEY_TAB, | |
667 NK_KEY_BACKSPACE, | |
668 NK_KEY_COPY, | |
669 NK_KEY_CUT, | |
670 NK_KEY_PASTE, | |
671 NK_KEY_UP, | |
672 NK_KEY_DOWN, | |
673 NK_KEY_LEFT, | |
674 NK_KEY_RIGHT, | |
675 /* Shortcuts: text field */ | |
676 NK_KEY_TEXT_INSERT_MODE, | |
677 NK_KEY_TEXT_REPLACE_MODE, | |
678 NK_KEY_TEXT_RESET_MODE, | |
679 NK_KEY_TEXT_LINE_START, | |
680 NK_KEY_TEXT_LINE_END, | |
681 NK_KEY_TEXT_START, | |
682 NK_KEY_TEXT_END, | |
683 NK_KEY_TEXT_UNDO, | |
684 NK_KEY_TEXT_REDO, | |
685 NK_KEY_TEXT_SELECT_ALL, | |
686 NK_KEY_TEXT_WORD_LEFT, | |
687 NK_KEY_TEXT_WORD_RIGHT, | |
688 /* Shortcuts: scrollbar */ | |
689 NK_KEY_SCROLL_START, | |
690 NK_KEY_SCROLL_END, | |
691 NK_KEY_SCROLL_DOWN, | |
692 NK_KEY_SCROLL_UP, | |
693 NK_KEY_MAX | |
694 }; | |
695 enum nk_buttons { | |
696 NK_BUTTON_LEFT, | |
697 NK_BUTTON_MIDDLE, | |
698 NK_BUTTON_RIGHT, | |
699 NK_BUTTON_DOUBLE, | |
700 NK_BUTTON_MAX | |
701 }; | |
702 /* nk_input_begin - Begins the input mirroring process by resetting text, scroll | |
703 * mouse previous mouse position and movement as well as key state transitions, | |
704 * Parameters: | |
705 * @ctx must point to an previously initialized `nk_context` struct */ | |
706 NK_API void nk_input_begin(struct nk_context*); | |
707 /* nk_input_motion - Mirrors current mouse position to nuklear | |
708 * Parameters: | |
709 * @ctx must point to an previously initialized `nk_context` struct | |
710 * @x must contain an integer describing the current mouse cursor x-position | |
711 * @y must contain an integer describing the current mouse cursor y-position */ | |
712 NK_API void nk_input_motion(struct nk_context*, int x, int y); | |
713 /* nk_input_key - Mirrors state of a specific key to nuklear | |
714 * Parameters: | |
715 * @ctx must point to an previously initialized `nk_context` struct | |
716 * @key must be any value specified in enum `nk_keys` that needs to be mirrored | |
717 * @down must be 0 for key is up and 1 for key is down */ | |
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down); | |
719 /* nk_input_button - Mirrors the state of a specific mouse button to nuklear | |
720 * Parameters: | |
721 * @ctx must point to an previously initialized `nk_context` struct | |
722 * @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored | |
723 * @x must contain an integer describing mouse cursor x-position on click up/down | |
724 * @y must contain an integer describing mouse cursor y-position on click up/down | |
725 * @down must be 0 for key is up and 1 for key is down */ | |
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down); | |
727 /* nk_input_scroll - Copies the last mouse scroll value to nuklear. Is generally | |
728 * a scroll value. So does not have to come from mouse and could also originate | |
729 * from touch for example. | |
730 * Parameters: | |
731 * @ctx must point to an previously initialized `nk_context` struct | |
732 * @val vector with both X- as well as Y-scroll value */ | |
733 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val); | |
734 /* nk_input_char - Copies a single ASCII character into an internal text buffer | |
735 * This is basically a helper function to quickly push ASCII characters into | |
736 * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into | |
737 * struct `nk_input` between `nk_input_begin` and `nk_input_end`. | |
738 * Parameters: | |
739 * @ctx must point to an previously initialized `nk_context` struct | |
740 * @c must be a single ASCII character preferable one that can be printed */ | |
741 NK_API void nk_input_char(struct nk_context*, char); | |
742 /* nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result | |
743 * into an internal text buffer. | |
744 * Note that you can only push up to NK_INPUT_MAX bytes into | |
745 * struct `nk_input` between `nk_input_begin` and `nk_input_end`. | |
746 * Parameters: | |
747 * @ctx must point to an previously initialized `nk_context` struct | |
748 * @glyph UTF-32 unicode codepoint */ | |
749 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); | |
750 /* nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result | |
751 * into an internal text buffer. | |
752 * Note that you can only push up to NK_INPUT_MAX bytes into | |
753 * struct `nk_input` between `nk_input_begin` and `nk_input_end`. | |
754 * Parameters: | |
755 * @ctx must point to an previously initialized `nk_context` struct | |
756 * @glyph UTF-32 unicode codepoint */ | |
757 NK_API void nk_input_unicode(struct nk_context*, nk_rune); | |
758 /* nk_input_end - End the input mirroring process by resetting mouse grabbing | |
759 * state to ensure the mouse cursor is not grabbed indefinitely. | |
760 * Parameters: | |
761 * @ctx must point to an previously initialized `nk_context` struct */ | |
762 NK_API void nk_input_end(struct nk_context*); | |
763 /* ============================================================================= | |
764 * | |
765 * DRAWING | |
766 * | |
767 * =============================================================================*/ | |
768 /* This library was designed to be render backend agnostic so it does | |
769 * not draw anything to screen directly. Instead all drawn shapes, widgets | |
770 * are made of, are buffered into memory and make up a command queue. | |
771 * Each frame therefore fills the command buffer with draw commands | |
772 * that then need to be executed by the user and his own render backend. | |
773 * After that the command buffer needs to be cleared and a new frame can be | |
774 * started. It is probably important to note that the command buffer is the main | |
775 * drawing API and the optional vertex buffer API only takes this format and | |
776 * converts it into a hardware accessible format. | |
777 * | |
778 * Usage | |
779 * ------------------- | |
780 * To draw all draw commands accumulated over a frame you need your own render | |
781 * backend able to draw a number of 2D primitives. This includes at least | |
782 * filled and stroked rectangles, circles, text, lines, triangles and scissors. | |
783 * As soon as this criterion is met you can iterate over each draw command | |
784 * and execute each draw command in a interpreter like fashion: | |
785 * | |
786 * const struct nk_command *cmd = 0; | |
787 * nk_foreach(cmd, &ctx) { | |
788 * switch (cmd->type) { | |
789 * case NK_COMMAND_LINE: | |
790 * your_draw_line_function(...) | |
791 * break; | |
792 * case NK_COMMAND_RECT | |
793 * your_draw_rect_function(...) | |
794 * break; | |
795 * case ...: | |
796 * [...] | |
797 * } | |
798 * | |
799 * In program flow context draw commands need to be executed after input has been | |
800 * gathered and the complete UI with windows and their contained widgets have | |
801 * been executed and before calling `nk_clear` which frees all previously | |
802 * allocated draw commands. | |
803 * | |
804 * struct nk_context ctx; | |
805 * nk_init_xxx(&ctx, ...); | |
806 * while (1) { | |
807 * Event evt; | |
808 * nk_input_begin(&ctx); | |
809 * while (GetEvent(&evt)) { | |
810 * if (evt.type == MOUSE_MOVE) | |
811 * nk_input_motion(&ctx, evt.motion.x, evt.motion.y); | |
812 * else if (evt.type == [...]) { | |
813 * [...] | |
814 * } | |
815 * } | |
816 * nk_input_end(&ctx); | |
817 * | |
818 * [...] | |
819 * | |
820 * const struct nk_command *cmd = 0; | |
821 * nk_foreach(cmd, &ctx) { | |
822 * switch (cmd->type) { | |
823 * case NK_COMMAND_LINE: | |
824 * your_draw_line_function(...) | |
825 * break; | |
826 * case NK_COMMAND_RECT | |
827 * your_draw_rect_function(...) | |
828 * break; | |
829 * case ...: | |
830 * [...] | |
831 * } | |
832 * nk_clear(&ctx); | |
833 * } | |
834 * nk_free(&ctx); | |
835 * | |
836 * You probably noticed that you have to draw all of the UI each frame which is | |
837 * quite wasteful. While the actual UI updating loop is quite fast rendering | |
838 * without actually needing it is not. So there are multiple things you could do. | |
839 * | |
840 * First is only update on input. This of course is only an option if your | |
841 * application only depends on the UI and does not require any outside calculations. | |
842 * If you actually only update on input make sure to update the UI two times each | |
843 * frame and call `nk_clear` directly after the first pass and only draw in | |
844 * the second pass. In addition it is recommended to also add additional timers | |
845 * to make sure the UI is not drawn more than a fixed number of frames per second. | |
846 * | |
847 * struct nk_context ctx; | |
848 * nk_init_xxx(&ctx, ...); | |
849 * while (1) { | |
850 * [...wait for input ] | |
851 * | |
852 * [...do two UI passes ...] | |
853 * do_ui(...) | |
854 * nk_clear(&ctx); | |
855 * do_ui(...) | |
856 * | |
857 * const struct nk_command *cmd = 0; | |
858 * nk_foreach(cmd, &ctx) { | |
859 * switch (cmd->type) { | |
860 * case NK_COMMAND_LINE: | |
861 * your_draw_line_function(...) | |
862 * break; | |
863 * case NK_COMMAND_RECT | |
864 * your_draw_rect_function(...) | |
865 * break; | |
866 * case ...: | |
867 * [...] | |
868 * } | |
869 * nk_clear(&ctx); | |
870 * } | |
871 * nk_free(&ctx); | |
872 * | |
873 * The second probably more applicable trick is to only draw if anything changed. | |
874 * It is not really useful for applications with continuous draw loop but | |
875 * quite useful for desktop applications. To actually get nuklear to only | |
876 * draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and | |
877 * allocate a memory buffer that will store each unique drawing output. | |
878 * After each frame you compare the draw command memory inside the library | |
879 * with your allocated buffer by memcmp. If memcmp detects differences | |
880 * you have to copy the command buffer into the allocated buffer | |
881 * and then draw like usual (this example uses fixed memory but you could | |
882 * use dynamically allocated memory). | |
883 * | |
884 * [... other defines ...] | |
885 * #define NK_ZERO_COMMAND_MEMORY | |
886 * #include "nuklear.h" | |
887 * | |
888 * struct nk_context ctx; | |
889 * void *last = calloc(1,64*1024); | |
890 * void *buf = calloc(1,64*1024); | |
891 * nk_init_fixed(&ctx, buf, 64*1024); | |
892 * while (1) { | |
893 * [...input...] | |
894 * [...ui...] | |
895 * | |
896 * void *cmds = nk_buffer_memory(&ctx.memory); | |
897 * if (memcmp(cmds, last, ctx.memory.allocated)) { | |
898 * memcpy(last,cmds,ctx.memory.allocated); | |
899 * const struct nk_command *cmd = 0; | |
900 * nk_foreach(cmd, &ctx) { | |
901 * switch (cmd->type) { | |
902 * case NK_COMMAND_LINE: | |
903 * your_draw_line_function(...) | |
904 * break; | |
905 * case NK_COMMAND_RECT | |
906 * your_draw_rect_function(...) | |
907 * break; | |
908 * case ...: | |
909 * [...] | |
910 * } | |
911 * } | |
912 * } | |
913 * nk_clear(&ctx); | |
914 * } | |
915 * nk_free(&ctx); | |
916 * | |
917 * Finally while using draw commands makes sense for higher abstracted platforms like | |
918 * X11 and Win32 or drawing libraries it is often desirable to use graphics | |
919 * hardware directly. Therefore it is possible to just define | |
920 * `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output. | |
921 * To access the vertex output you first have to convert all draw commands into | |
922 * vertexes by calling `nk_convert` which takes in your preferred vertex format. | |
923 * After successfully converting all draw commands just iterate over and execute all | |
924 * vertex draw commands: | |
925 * | |
926 * struct nk_convert_config cfg = {}; | |
927 * static const struct nk_draw_vertex_layout_element vertex_layout[] = { | |
928 * {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, | |
929 * {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)}, | |
930 * {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)}, | |
931 * {NK_VERTEX_LAYOUT_END} | |
932 * }; | |
933 * cfg.shape_AA = NK_ANTI_ALIASING_ON; | |
934 * cfg.line_AA = NK_ANTI_ALIASING_ON; | |
935 * cfg.vertex_layout = vertex_layout; | |
936 * cfg.vertex_size = sizeof(struct your_vertex); | |
937 * cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex); | |
938 * cfg.circle_segment_count = 22; | |
939 * cfg.curve_segment_count = 22; | |
940 * cfg.arc_segment_count = 22; | |
941 * cfg.global_alpha = 1.0f; | |
942 * cfg.null = dev->null; | |
943 * | |
944 * struct nk_buffer cmds, verts, idx; | |
945 * nk_buffer_init_default(&cmds); | |
946 * nk_buffer_init_default(&verts); | |
947 * nk_buffer_init_default(&idx); | |
948 * nk_convert(&ctx, &cmds, &verts, &idx, &cfg); | |
949 * nk_draw_foreach(cmd, &ctx, &cmds) { | |
950 * if (!cmd->elem_count) continue; | |
951 * [...] | |
952 * } | |
953 * nk_buffer_free(&cms); | |
954 * nk_buffer_free(&verts); | |
955 * nk_buffer_free(&idx); | |
956 * | |
957 * Reference | |
958 * ------------------- | |
959 * nk__begin - Returns the first draw command in the context draw command list to be drawn | |
960 * nk__next - Increments the draw command iterator to the next command inside the context draw command list | |
961 * nk_foreach - Iterates over each draw command inside the context draw command list | |
962 * | |
963 * nk_convert - Converts from the abstract draw commands list into a hardware accessible vertex format | |
964 * nk__draw_begin - Returns the first vertex command in the context vertex draw list to be executed | |
965 * nk__draw_next - Increments the vertex command iterator to the next command inside the context vertex command list | |
966 * nk__draw_end - Returns the end of the vertex draw list | |
967 * nk_draw_foreach - Iterates over each vertex draw command inside the vertex draw list | |
968 */ | |
969 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; | |
970 enum nk_convert_result { | |
971 NK_CONVERT_SUCCESS = 0, | |
972 NK_CONVERT_INVALID_PARAM = 1, | |
973 NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1), | |
974 NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2), | |
975 NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3) | |
976 }; | |
977 struct nk_draw_null_texture { | |
978 nk_handle texture; /* texture handle to a texture with a white pixel */ | |
979 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ | |
980 }; | |
981 struct nk_convert_config { | |
982 float global_alpha; /* global alpha value */ | |
983 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ | |
984 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ | |
985 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ | |
986 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ | |
987 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ | |
988 struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ | |
989 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ | |
990 nk_size vertex_size; /* sizeof one vertex for vertex packing */ | |
991 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ | |
992 }; | |
993 /* nk__begin - Returns a draw command list iterator to iterate all draw | |
994 * commands accumulated over one frame. | |
995 * Parameters: | |
996 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
997 * Return values: | |
998 * draw command pointer pointing to the first command inside the draw command list */ | |
999 NK_API const struct nk_command* nk__begin(struct nk_context*); | |
1000 /* nk__next - Returns a draw command list iterator to iterate all draw | |
1001 * Parameters: | |
1002 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1003 * @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next` | |
1004 * Return values: | |
1005 * draw command pointer pointing to the next command inside the draw command list */ | |
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); | |
1007 /* nk_foreach - Iterates over each draw command inside the context draw command list | |
1008 * Parameters: | |
1009 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1010 * @cmd pointer initialized to NULL */ | |
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c)) | |
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
1013 /* nk_convert - converts all internal draw command into vertex draw commands and fills | |
1014 * three buffers with vertexes, vertex draw commands and vertex indices. The vertex format | |
1015 * as well as some other configuration values have to be configured by filling out a | |
1016 * `nk_convert_config` struct. | |
1017 * Parameters: | |
1018 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1019 * @cmds must point to a previously initialized buffer to hold converted vertex draw commands | |
1020 * @vertices must point to a previously initialized buffer to hold all produced vertices | |
1021 * @elements must point to a previously initialized buffer to hold all produced vertex indices | |
1022 * @config must point to a filled out `nk_config` struct to configure the conversion process | |
1023 * Returns: | |
1024 * returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */ | |
1025 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); | |
1026 /* nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer | |
1027 * Parameters: | |
1028 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1029 * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer | |
1030 * Return values: | |
1031 * vertex draw command pointer pointing to the first command inside the vertex draw command buffer */ | |
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); | |
1033 /* nk__draw_end - Returns the vertex draw command at the end of the vertex draw command buffer | |
1034 * Parameters: | |
1035 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1036 * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer | |
1037 * Return values: | |
1038 * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */ | |
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); | |
1040 /* nk__draw_next - Increments the vertex draw command buffer iterator | |
1041 * Parameters: | |
1042 * @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command | |
1043 * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer | |
1044 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame | |
1045 * Return values: | |
1046 * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */ | |
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); | |
1048 /* nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer | |
1049 * Parameters: | |
1050 * @cmd nk_draw_command pointer set to NULL | |
1051 * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer | |
1052 * @ctx must point to an previously initialized `nk_context` struct at the end of a frame */ | |
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) | |
1054 #endif | |
1055 /* ============================================================================= | |
1056 * | |
1057 * WINDOW | |
1058 * | |
1059 * ============================================================================= | |
1060 * Windows are the main persistent state used inside nuklear and are life time | |
1061 * controlled by simply "retouching" (i.e. calling) each window each frame. | |
1062 * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx` | |
1063 * and `nk_end`. Calling any widgets outside these two functions will result in an | |
1064 * assert in debug or no state change in release mode. | |
1065 * | |
1066 * Each window holds frame persistent state like position, size, flags, state tables, | |
1067 * and some garbage collected internal persistent widget state. Each window | |
1068 * is linked into a window stack list which determines the drawing and overlapping | |
1069 * order. The topmost window thereby is the currently active window. | |
1070 * | |
1071 * To change window position inside the stack occurs either automatically by | |
1072 * user input by being clicked on or programmatically by calling `nk_window_focus`. | |
1073 * Windows by default are visible unless explicitly being defined with flag | |
1074 * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag | |
1075 * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling | |
1076 * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`. | |
1077 * | |
1078 * Usage | |
1079 * ------------------- | |
1080 * To create and keep a window you have to call one of the two `nk_begin_xxx` | |
1081 * functions to start window declarations and `nk_end` at the end. Furthermore it | |
1082 * is recommended to check the return value of `nk_begin_xxx` and only process | |
1083 * widgets inside the window if the value is not 0. Either way you have to call | |
1084 * `nk_end` at the end of window declarations. Furthermore, do not attempt to | |
1085 * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not | |
1086 * in a segmentation fault. | |
1087 * | |
1088 * if (nk_begin_xxx(...) { | |
1089 * [... widgets ...] | |
1090 * } | |
1091 * nk_end(ctx); | |
1092 * | |
1093 * In the grand concept window and widget declarations need to occur after input | |
1094 * handling and before drawing to screen. Not doing so can result in higher | |
1095 * latency or at worst invalid behavior. Furthermore make sure that `nk_clear` | |
1096 * is called at the end of the frame. While nuklear's default platform backends | |
1097 * already call `nk_clear` for you if you write your own backend not calling | |
1098 * `nk_clear` can cause asserts or even worse undefined behavior. | |
1099 * | |
1100 * struct nk_context ctx; | |
1101 * nk_init_xxx(&ctx, ...); | |
1102 * while (1) { | |
1103 * Event evt; | |
1104 * nk_input_begin(&ctx); | |
1105 * while (GetEvent(&evt)) { | |
1106 * if (evt.type == MOUSE_MOVE) | |
1107 * nk_input_motion(&ctx, evt.motion.x, evt.motion.y); | |
1108 * else if (evt.type == [...]) { | |
1109 * nk_input_xxx(...); | |
1110 * } | |
1111 * } | |
1112 * nk_input_end(&ctx); | |
1113 * | |
1114 * if (nk_begin_xxx(...) { | |
1115 * [...] | |
1116 * } | |
1117 * nk_end(ctx); | |
1118 * | |
1119 * const struct nk_command *cmd = 0; | |
1120 * nk_foreach(cmd, &ctx) { | |
1121 * case NK_COMMAND_LINE: | |
1122 * your_draw_line_function(...) | |
1123 * break; | |
1124 * case NK_COMMAND_RECT | |
1125 * your_draw_rect_function(...) | |
1126 * break; | |
1127 * case ...: | |
1128 * [...] | |
1129 * } | |
1130 * nk_clear(&ctx); | |
1131 * } | |
1132 * nk_free(&ctx); | |
1133 * | |
1134 * Reference | |
1135 * ------------------- | |
1136 * nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed | |
1137 * nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title | |
1138 * nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup | |
1139 * | |
1140 * nk_window_find - finds and returns the window with give name | |
1141 * nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window. | |
1142 * nk_window_get_position - returns the position of the currently processed window | |
1143 * nk_window_get_size - returns the size with width and height of the currently processed window | |
1144 * nk_window_get_width - returns the width of the currently processed window | |
1145 * nk_window_get_height - returns the height of the currently processed window | |
1146 * nk_window_get_panel - returns the underlying panel which contains all processing state of the current window | |
1147 * nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window | |
1148 * nk_window_get_content_region_min - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window | |
1149 * nk_window_get_content_region_max - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window | |
1150 * nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window | |
1151 * nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets | |
1152 * | |
1153 * nk_window_has_focus - returns if the currently processed window is currently active | |
1154 * nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed | |
1155 * nk_window_is_closed - returns if the currently processed window was closed | |
1156 * nk_window_is_hidden - returns if the currently processed window was hidden | |
1157 * nk_window_is_active - same as nk_window_has_focus for some reason | |
1158 * nk_window_is_hovered - returns if the currently processed window is currently being hovered by mouse | |
1159 * nk_window_is_any_hovered - return if any window currently hovered | |
1160 * nk_item_is_any_active - returns if any window or widgets is currently hovered or active | |
1161 * | |
1162 * nk_window_set_bounds - updates position and size of the currently processed window | |
1163 * nk_window_set_position - updates position of the currently process window | |
1164 * nk_window_set_size - updates the size of the currently processed window | |
1165 * nk_window_set_focus - set the currently processed window as active window | |
1166 * | |
1167 * nk_window_close - closes the window with given window name which deletes the window at the end of the frame | |
1168 * nk_window_collapse - collapses the window with given window name | |
1169 * nk_window_collapse_if - collapses the window with given window name if the given condition was met | |
1170 * nk_window_show - hides a visible or reshows a hidden window | |
1171 * nk_window_show_if - hides/shows a window depending on condition | |
1172 */ | |
1173 enum nk_panel_flags { | |
1174 NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */ | |
1175 NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */ | |
1176 NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */ | |
1177 NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */ | |
1178 NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */ | |
1179 NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */ | |
1180 NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */ | |
1181 NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */ | |
1182 NK_WINDOW_BACKGROUND = NK_FLAG(8), /* Always keep window in the background */ | |
1183 NK_WINDOW_SCALE_LEFT = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/ | |
1184 NK_WINDOW_NO_INPUT = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */ | |
1185 }; | |
1186 /* nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed | |
1187 * Parameters: | |
1188 * @ctx must point to an previously initialized `nk_context` struct | |
1189 * @title window title and identifier. Needs to be persistent over frames to identify the window | |
1190 * @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 | |
1191 * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors | |
1192 * Return values: | |
1193 * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/ | |
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); | |
1195 /* nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title | |
1196 * Parameters: | |
1197 * @ctx must point to an previously initialized `nk_context` struct | |
1198 * @name window identifier. Needs to be persistent over frames to identify the window | |
1199 * @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set | |
1200 * @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 | |
1201 * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors | |
1202 * Return values: | |
1203 * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/ | |
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); | |
1205 /* nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup. | |
1206 * All widget calls after this functions will result in asserts or no state changes | |
1207 * Parameters: | |
1208 * @ctx must point to an previously initialized `nk_context` struct */ | |
1209 NK_API void nk_end(struct nk_context *ctx); | |
1210 /* nk_window_find - finds and returns the window with give name | |
1211 * Parameters: | |
1212 * @ctx must point to an previously initialized `nk_context` struct | |
1213 * @name window identifier | |
1214 * Return values: | |
1215 * returns a `nk_window` struct pointing to the identified window or 0 if no window with given name was found */ | |
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); | |
1217 /* nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window. | |
1218 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1219 * Parameters: | |
1220 * @ctx must point to an previously initialized `nk_context` struct | |
1221 * Return values: | |
1222 * returns a `nk_rect` struct with window upper left position and size */ | |
1223 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); | |
1224 /* nk_window_get_position - returns the position of the currently processed window. | |
1225 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1226 * Parameters: | |
1227 * @ctx must point to an previously initialized `nk_context` struct | |
1228 * Return values: | |
1229 * returns a `nk_vec2` struct with window upper left position */ | |
1230 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); | |
1231 /* nk_window_get_size - returns the size with width and height of the currently processed window. | |
1232 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1233 * Parameters: | |
1234 * @ctx must point to an previously initialized `nk_context` struct | |
1235 * Return values: | |
1236 * returns a `nk_vec2` struct with window size */ | |
1237 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); | |
1238 /* nk_window_get_width - returns the width of the currently processed window. | |
1239 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1240 * Parameters: | |
1241 * @ctx must point to an previously initialized `nk_context` struct | |
1242 * Return values: | |
1243 * returns the window width */ | |
1244 NK_API float nk_window_get_width(const struct nk_context*); | |
1245 /* nk_window_get_height - returns the height of the currently processed window. | |
1246 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1247 * Parameters: | |
1248 * @ctx must point to an previously initialized `nk_context` struct | |
1249 * Return values: | |
1250 * returns the window height */ | |
1251 NK_API float nk_window_get_height(const struct nk_context*); | |
1252 /* nk_window_get_panel - returns the underlying panel which contains all processing state of the current window. | |
1253 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1254 * Parameters: | |
1255 * @ctx must point to an previously initialized `nk_context` struct | |
1256 * Return values: | |
1257 * returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */ | |
1258 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); | |
1259 /* nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window. | |
1260 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1261 * Parameters: | |
1262 * @ctx must point to an previously initialized `nk_context` struct | |
1263 * Return values: | |
1264 * returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */ | |
1265 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); | |
1266 /* nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window. | |
1267 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1268 * Parameters: | |
1269 * @ctx must point to an previously initialized `nk_context` struct | |
1270 * Return values: | |
1271 * returns `nk_vec2` struct with upper left screen position (no scrollbar offset) of the visible space inside the current window */ | |
1272 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); | |
1273 /* nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window. | |
1274 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1275 * Parameters: | |
1276 * @ctx must point to an previously initialized `nk_context` struct | |
1277 * Return values: | |
1278 * returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */ | |
1279 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); | |
1280 /* nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window | |
1281 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1282 * Parameters: | |
1283 * @ctx must point to an previously initialized `nk_context` struct | |
1284 * Return values: | |
1285 * returns `nk_vec2` struct with size the visible space inside the current window */ | |
1286 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); | |
1287 /* nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets | |
1288 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1289 * Parameters: | |
1290 * @ctx must point to an previously initialized `nk_context` struct | |
1291 * Return values: | |
1292 * returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */ | |
1293 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); | |
1294 /* nk_window_has_focus - returns if the currently processed window is currently active | |
1295 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1296 * Parameters: | |
1297 * @ctx must point to an previously initialized `nk_context` struct | |
1298 * Return values: | |
1299 * returns 0 if current window is not active or 1 if it is */ | |
1300 NK_API int nk_window_has_focus(const struct nk_context*); | |
1301 /* nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed | |
1302 * Parameters: | |
1303 * @ctx must point to an previously initialized `nk_context` struct | |
1304 * @name of window you want to check is collapsed | |
1305 * Return values: | |
1306 * returns 1 if current window is minimized and 0 if window not found or is not minimized */ | |
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name); | |
1308 /* nk_window_is_closed - returns if the window with given name was closed by calling `nk_close` | |
1309 * Parameters: | |
1310 * @ctx must point to an previously initialized `nk_context` struct | |
1311 * @name of window you want to check is closed | |
1312 * Return values: | |
1313 * returns 1 if current window was closed or 0 window not found or not closed */ | |
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*); | |
1315 /* nk_window_is_hidden - returns if the window with given name is hidden | |
1316 * Parameters: | |
1317 * @ctx must point to an previously initialized `nk_context` struct | |
1318 * @name of window you want to check is hidden | |
1319 * Return values: | |
1320 * returns 1 if current window is hidden or 0 window not found or visible */ | |
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*); | |
1322 /* nk_window_is_active - same as nk_window_has_focus for some reason | |
1323 * Parameters: | |
1324 * @ctx must point to an previously initialized `nk_context` struct | |
1325 * @name of window you want to check is hidden | |
1326 * Return values: | |
1327 * returns 1 if current window is active or 0 window not found or not active */ | |
1328 NK_API int nk_window_is_active(struct nk_context*, const char*); | |
1329 /* nk_window_is_hovered - return if the current window is being hovered | |
1330 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1331 * Parameters: | |
1332 * @ctx must point to an previously initialized `nk_context` struct | |
1333 * Return values: | |
1334 * returns 1 if current window is hovered or 0 otherwise */ | |
1335 NK_API int nk_window_is_hovered(struct nk_context*); | |
1336 /* nk_window_is_any_hovered - returns if the any window is being hovered | |
1337 * Parameters: | |
1338 * @ctx must point to an previously initialized `nk_context` struct | |
1339 * Return values: | |
1340 * returns 1 if any window is hovered or 0 otherwise */ | |
1341 NK_API int nk_window_is_any_hovered(struct nk_context*); | |
1342 /* nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active. | |
1343 * Can be used to decide if input should be processed by UI or your specific input handling. | |
1344 * Example could be UI and 3D camera to move inside a 3D space. | |
1345 * Parameters: | |
1346 * @ctx must point to an previously initialized `nk_context` struct | |
1347 * Return values: | |
1348 * returns 1 if any window is hovered or any item is active or 0 otherwise */ | |
1349 NK_API int nk_item_is_any_active(struct nk_context*); | |
1350 /* nk_window_set_bounds - updates position and size of the currently processed window | |
1351 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1352 * Parameters: | |
1353 * @ctx must point to an previously initialized `nk_context` struct | |
1354 * @name of the window to modify both position and size | |
1355 * @bounds points to a `nk_rect` struct with the new position and size of currently active window */ | |
1356 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); | |
1357 /* nk_window_set_position - updates position of the currently processed window | |
1358 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1359 * Parameters: | |
1360 * @ctx must point to an previously initialized `nk_context` struct | |
1361 * @name of the window to modify position of | |
1362 * @pos points to a `nk_vec2` struct with the new position of currently active window */ | |
1363 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); | |
1364 /* nk_window_set_size - updates size of the currently processed window | |
1365 * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end` | |
1366 * Parameters: | |
1367 * @ctx must point to an previously initialized `nk_context` struct | |
1368 * @name of the window to modify size of | |
1369 * @size points to a `nk_vec2` struct with the new size of currently active window */ | |
1370 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); | |
1371 /* nk_window_set_focus - sets the window with given name as active | |
1372 * Parameters: | |
1373 * @ctx must point to an previously initialized `nk_context` struct | |
1374 * @name of the window to be set active */ | |
1375 NK_API void nk_window_set_focus(struct nk_context*, const char *name); | |
1376 /* nk_window_close - closed a window and marks it for being freed at the end of the frame | |
1377 * Parameters: | |
1378 * @ctx must point to an previously initialized `nk_context` struct | |
1379 * @name of the window to be closed */ | |
1380 NK_API void nk_window_close(struct nk_context *ctx, const char *name); | |
1381 /* nk_window_collapse - updates collapse state of a window with given name | |
1382 * Parameters: | |
1383 * @ctx must point to an previously initialized `nk_context` struct | |
1384 * @name of the window to be either collapse or maximize */ | |
1385 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); | |
1386 /* nk_window_collapse - updates collapse state of a window with given name if given condition is met | |
1387 * Parameters: | |
1388 * @ctx must point to an previously initialized `nk_context` struct | |
1389 * @name of the window to be either collapse or maximize | |
1390 * @state the window should be put into | |
1391 * @condition that has to be true to actually commit the collapse state change */ | |
1392 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); | |
1393 /* nk_window_show - updates visibility state of a window with given name | |
1394 * Parameters: | |
1395 * @ctx must point to an previously initialized `nk_context` struct | |
1396 * @name of the window to be either collapse or maximize | |
1397 * @state with either visible or hidden to modify the window with */ | |
1398 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); | |
1399 /* nk_window_show_if - updates visibility state of a window with given name if a given condition is met | |
1400 * Parameters: | |
1401 * @ctx must point to an previously initialized `nk_context` struct | |
1402 * @name of the window to be either collapse or maximize | |
1403 * @state with either visible or hidden to modify the window with | |
1404 * @condition that has to be true to actually commit the visible state change */ | |
1405 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); | |
1406 /* ============================================================================= | |
1407 * | |
1408 * LAYOUT | |
1409 * | |
1410 * ============================================================================= */ | |
1411 /* Layouting in general describes placing widget inside a window with position and size. | |
1412 * While in this particular implementation there are five different APIs for layouting | |
1413 * each with different trade offs between control and ease of use. | |
1414 * | |
1415 * All layouting methods in this library are based around the concept of a row. | |
1416 * A row has a height the window content grows by and a number of columns and each | |
1417 * layouting method specifies how each widget is placed inside the row. | |
1418 * After a row has been allocated by calling a layouting functions and then | |
1419 * filled with widgets will advance an internal pointer over the allocated row. | |
1420 * | |
1421 * To actually define a layout you just call the appropriate layouting function | |
1422 * and each subsequent widget call will place the widget as specified. Important | |
1423 * here is that if you define more widgets then columns defined inside the layout | |
1424 * functions it will allocate the next row without you having to make another layouting | |
1425 * call. | |
1426 * | |
1427 * Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API | |
1428 * is that you have to define the row height for each. However the row height | |
1429 * often depends on the height of the font. | |
1430 * | |
1431 * To fix that internally nuklear uses a minimum row height that is set to the | |
1432 * height plus padding of currently active font and overwrites the row height | |
1433 * value if zero. | |
1434 * | |
1435 * If you manually want to change the minimum row height then | |
1436 * use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to | |
1437 * reset it back to be derived from font height. | |
1438 * | |
1439 * Also if you change the font in nuklear it will automatically change the minimum | |
1440 * row height for you and. This means if you change the font but still want | |
1441 * a minimum row height smaller than the font you have to repush your value. | |
1442 * | |
1443 * For actually more advanced UI I would even recommend using the `nk_layout_space_xxx` | |
1444 * layouting method in combination with a cassowary constraint solver (there are | |
1445 * some versions on github with permissive license model) to take over all control over widget | |
1446 * layouting yourself. However for quick and dirty layouting using all the other layouting | |
1447 * functions should be fine. | |
1448 * | |
1449 * Usage | |
1450 * ------------------- | |
1451 * 1.) nk_layout_row_dynamic | |
1452 * The easiest layouting function is `nk_layout_row_dynamic`. It provides each | |
1453 * widgets with same horizontal space inside the row and dynamically grows | |
1454 * if the owning window grows in width. So the number of columns dictates | |
1455 * the size of each widget dynamically by formula: | |
1456 * | |
1457 * widget_width = (window_width - padding - spacing) * (1/colum_count) | |
1458 * | |
1459 * Just like all other layouting APIs if you define more widget than columns this | |
1460 * library will allocate a new row and keep all layouting parameters previously | |
1461 * defined. | |
1462 * | |
1463 * if (nk_begin_xxx(...) { | |
1464 * // first row with height: 30 composed of two widgets | |
1465 * nk_layout_row_dynamic(&ctx, 30, 2); | |
1466 * nk_widget(...); | |
1467 * nk_widget(...); | |
1468 * | |
1469 * // second row with same parameter as defined above | |
1470 * nk_widget(...); | |
1471 * nk_widget(...); | |
1472 * | |
1473 * // third row uses 0 for height which will use auto layouting | |
1474 * nk_layout_row_dynamic(&ctx, 0, 2); | |
1475 * nk_widget(...); | |
1476 * nk_widget(...); | |
1477 * } | |
1478 * nk_end(...); | |
1479 * | |
1480 * 2.) nk_layout_row_static | |
1481 * Another easy layouting function is `nk_layout_row_static`. It provides each | |
1482 * widget with same horizontal pixel width inside the row and does not grow | |
1483 * if the owning window scales smaller or bigger. | |
1484 * | |
1485 * if (nk_begin_xxx(...) { | |
1486 * // first row with height: 30 composed of two widgets with width: 80 | |
1487 * nk_layout_row_static(&ctx, 30, 80, 2); | |
1488 * nk_widget(...); | |
1489 * nk_widget(...); | |
1490 * | |
1491 * // second row with same parameter as defined above | |
1492 * nk_widget(...); | |
1493 * nk_widget(...); | |
1494 * | |
1495 * // third row uses 0 for height which will use auto layouting | |
1496 * nk_layout_row_static(&ctx, 0, 80, 2); | |
1497 * nk_widget(...); | |
1498 * nk_widget(...); | |
1499 * } | |
1500 * nk_end(...); | |
1501 * | |
1502 * 3.) nk_layout_row_xxx | |
1503 * A little bit more advanced layouting API are functions `nk_layout_row_begin`, | |
1504 * `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly | |
1505 * specify each column pixel or window ratio in a row. It supports either | |
1506 * directly setting per column pixel width or widget window ratio but not | |
1507 * both. Furthermore it is a immediate mode API so each value is directly | |
1508 * pushed before calling a widget. Therefore the layout is not automatically | |
1509 * repeating like the last two layouting functions. | |
1510 * | |
1511 * if (nk_begin_xxx(...) { | |
1512 * // first row with height: 25 composed of two widgets with width 60 and 40 | |
1513 * nk_layout_row_begin(ctx, NK_STATIC, 25, 2); | |
1514 * nk_layout_row_push(ctx, 60); | |
1515 * nk_widget(...); | |
1516 * nk_layout_row_push(ctx, 40); | |
1517 * nk_widget(...); | |
1518 * nk_layout_row_end(ctx); | |
1519 * | |
1520 * // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 | |
1521 * nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); | |
1522 * nk_layout_row_push(ctx, 0.25f); | |
1523 * nk_widget(...); | |
1524 * nk_layout_row_push(ctx, 0.75f); | |
1525 * nk_widget(...); | |
1526 * nk_layout_row_end(ctx); | |
1527 * | |
1528 * // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 | |
1529 * nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); | |
1530 * nk_layout_row_push(ctx, 0.25f); | |
1531 * nk_widget(...); | |
1532 * nk_layout_row_push(ctx, 0.75f); | |
1533 * nk_widget(...); | |
1534 * nk_layout_row_end(ctx); | |
1535 * } | |
1536 * nk_end(...); | |
1537 * | |
1538 * 4.) nk_layout_row | |
1539 * The array counterpart to API nk_layout_row_xxx is the single nk_layout_row | |
1540 * functions. Instead of pushing either pixel or window ratio for every widget | |
1541 * it allows to define it by array. The trade of for less control is that | |
1542 * `nk_layout_row` is automatically repeating. Otherwise the behavior is the | |
1543 * same. | |
1544 * | |
1545 * if (nk_begin_xxx(...) { | |
1546 * // two rows with height: 30 composed of two widgets with width 60 and 40 | |
1547 * const float size[] = {60,40}; | |
1548 * nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); | |
1549 * nk_widget(...); | |
1550 * nk_widget(...); | |
1551 * nk_widget(...); | |
1552 * nk_widget(...); | |
1553 * | |
1554 * // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 | |
1555 * const float ratio[] = {0.25, 0.75}; | |
1556 * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); | |
1557 * nk_widget(...); | |
1558 * nk_widget(...); | |
1559 * nk_widget(...); | |
1560 * nk_widget(...); | |
1561 * | |
1562 * // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 | |
1563 * const float ratio[] = {0.25, 0.75}; | |
1564 * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); | |
1565 * nk_widget(...); | |
1566 * nk_widget(...); | |
1567 * nk_widget(...); | |
1568 * nk_widget(...); | |
1569 * } | |
1570 * nk_end(...); | |
1571 * | |
1572 * 5.) nk_layout_row_template_xxx | |
1573 * The most complex and second most flexible API is a simplified flexbox version without | |
1574 * line wrapping and weights for dynamic widgets. It is an immediate mode API but | |
1575 * unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called | |
1576 * before calling the templated widgets. | |
1577 * The row template layout has three different per widget size specifier. The first | |
1578 * one is the static widget size specifier with fixed widget pixel width. They do | |
1579 * not grow if the row grows and will always stay the same. The second size | |
1580 * specifier is nk_layout_row_template_push_variable which defines a | |
1581 * minimum widget size but it also can grow if more space is available not taken | |
1582 * by other widgets. Finally there are dynamic widgets which are completely flexible | |
1583 * and unlike variable widgets can even shrink to zero if not enough space | |
1584 * is provided. | |
1585 * | |
1586 * if (nk_begin_xxx(...) { | |
1587 * // two rows with height: 30 composed of three widgets | |
1588 * nk_layout_row_template_begin(ctx, 30); | |
1589 * nk_layout_row_template_push_dynamic(ctx); | |
1590 * nk_layout_row_template_push_variable(ctx, 80); | |
1591 * nk_layout_row_template_push_static(ctx, 80); | |
1592 * nk_layout_row_template_end(ctx); | |
1593 * | |
1594 * nk_widget(...); // dynamic widget can go to zero if not enough space | |
1595 * nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space | |
1596 * nk_widget(...); // static widget with fixed 80 pixel width | |
1597 * | |
1598 * // second row same layout | |
1599 * nk_widget(...); | |
1600 * nk_widget(...); | |
1601 * nk_widget(...); | |
1602 * } | |
1603 * nk_end(...); | |
1604 * | |
1605 * 6.) nk_layout_space_xxx | |
1606 * Finally the most flexible API directly allows you to place widgets inside the | |
1607 * window. The space layout API is an immediate mode API which does not support | |
1608 * row auto repeat and directly sets position and size of a widget. Position | |
1609 * and size hereby can be either specified as ratio of allocated space or | |
1610 * allocated space local position and pixel size. Since this API is quite | |
1611 * powerful there are a number of utility functions to get the available space | |
1612 * and convert between local allocated space and screen space. | |
1613 * | |
1614 * if (nk_begin_xxx(...) { | |
1615 * // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) | |
1616 * nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); | |
1617 * nk_layout_space_push(ctx, nk_rect(0,0,150,200)); | |
1618 * nk_widget(...); | |
1619 * nk_layout_space_push(ctx, nk_rect(200,200,100,200)); | |
1620 * nk_widget(...); | |
1621 * nk_layout_space_end(ctx); | |
1622 * | |
1623 * // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) | |
1624 * nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); | |
1625 * nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); | |
1626 * nk_widget(...); | |
1627 * nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); | |
1628 * nk_widget(...); | |
1629 * } | |
1630 * nk_end(...); | |
1631 * | |
1632 * Reference | |
1633 * ------------------- | |
1634 * nk_layout_set_min_row_height - set the currently used minimum row height to a specified value | |
1635 * nk_layout_reset_min_row_height - resets the currently used minimum row height to font height | |
1636 * | |
1637 * nk_layout_widget_bounds - calculates current width a static layout row can fit inside a window | |
1638 * nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size | |
1639 * | |
1640 * nk_layout_row_dynamic - current layout is divided into n same sized growing columns | |
1641 * nk_layout_row_static - current layout is divided into n same fixed sized columns | |
1642 * nk_layout_row_begin - starts a new row with given height and number of columns | |
1643 * nk_layout_row_push - pushes another column with given size or window ratio | |
1644 * nk_layout_row_end - finished previously started row | |
1645 * nk_layout_row - specifies row columns in array as either window ratio or size | |
1646 * | |
1647 * nk_layout_row_template_begin - begins the row template declaration | |
1648 * nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space | |
1649 * nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width | |
1650 * nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size | |
1651 * nk_layout_row_template_end - marks the end of the row template | |
1652 * | |
1653 * nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size | |
1654 * nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio | |
1655 * nk_layout_space_end - marks the end of the layouting space | |
1656 * | |
1657 * nk_layout_space_bounds - callable after nk_layout_space_begin and returns total space allocated | |
1658 * nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space | |
1659 * nk_layout_space_to_local - converts vector from screen space into nk_layout_space coordinates | |
1660 * nk_layout_space_rect_to_screen - converts rectangle from nk_layout_space coordinate space into screen space | |
1661 * nk_layout_space_rect_to_local - converts rectangle from screen space into nk_layout_space coordinates | |
1662 */ | |
1663 /* nk_layout_set_min_row_height - sets the currently used minimum row height. | |
1664 * IMPORTANT: The passed height needs to include both your preferred row height | |
1665 * as well as padding. No internal padding is added. | |
1666 * Parameters: | |
1667 * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` | |
1668 * @height new minimum row height to be used for auto generating the row height */ | |
1669 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height); | |
1670 /* nk_layout_reset_min_row_height - Reset the currently used minimum row height | |
1671 * back to font height + text padding + additional padding (style_window.min_row_height_padding) | |
1672 * Parameters: | |
1673 * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` */ | |
1674 NK_API void nk_layout_reset_min_row_height(struct nk_context*); | |
1675 /* nk_layout_widget_bounds - returns the width of the next row allocate by one of the layouting functions | |
1676 * Parameters: | |
1677 * @ctx must point to an previously initialized `nk_context` */ | |
1678 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*); | |
1679 /* nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size | |
1680 * Parameters: | |
1681 * @ctx must point to an previously initialized `nk_context` | |
1682 * @pixel_width to convert to window ratio */ | |
1683 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); | |
1684 /* nk_layout_row_dynamic - Sets current row layout to share horizontal space | |
1685 * between @cols number of widgets evenly. Once called all subsequent widget | |
1686 * calls greater than @cols will allocate a new row with same layout. | |
1687 * Parameters: | |
1688 * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` | |
1689 * @row_height holds height of each widget in row or zero for auto layouting | |
1690 * @cols number of widget inside row */ | |
1691 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); | |
1692 /* nk_layout_row_static - Sets current row layout to fill @cols number of widgets | |
1693 * in row with same @item_width horizontal size. Once called all subsequent widget | |
1694 * calls greater than @cols will allocate a new row with same layout. | |
1695 * Parameters: | |
1696 * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` | |
1697 * @height holds row height to allocate from panel for widget height | |
1698 * @item_width holds width of each widget in row | |
1699 * @cols number of widget inside row */ | |
1700 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); | |
1701 /* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns. | |
1702 * Parameters: | |
1703 * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` | |
1704 * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns | |
1705 * @row_height holds height of each widget in row or zero for auto layouting | |
1706 * @cols number of widget inside row */ | |
1707 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); | |
1708 /* nk_layout_row_push - Specifies either window ratio or width of a single column | |
1709 * Parameters: | |
1710 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin` | |
1711 * @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */ | |
1712 NK_API void nk_layout_row_push(struct nk_context*, float value); | |
1713 /* nk_layout_row_end - finished previously started row | |
1714 * Parameters: | |
1715 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin` */ | |
1716 NK_API void nk_layout_row_end(struct nk_context*); | |
1717 /* nk_layout_row - specifies row columns in array as either window ratio or size | |
1718 * Parameters: | |
1719 * @ctx must point to an previously initialized `nk_context` | |
1720 * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns | |
1721 * @row_height holds height of each widget in row or zero for auto layouting | |
1722 * @cols number of widget inside row */ | |
1723 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); | |
1724 /* nk_layout_row_template_begin - Begins the row template declaration | |
1725 * Parameters: | |
1726 * @ctx must point to an previously initialized `nk_context` struct | |
1727 * @row_height holds height of each widget in row or zero for auto layouting */ | |
1728 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height); | |
1729 /* nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space | |
1730 * Parameters: | |
1731 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */ | |
1732 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*); | |
1733 /* nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width | |
1734 * Parameters: | |
1735 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` | |
1736 * @min_width holds the minimum pixel width the next column must be */ | |
1737 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width); | |
1738 /* nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size | |
1739 * Parameters: | |
1740 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` | |
1741 * @width holds the absolute pixel width value the next column must be */ | |
1742 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width); | |
1743 /* nk_layout_row_template_end - marks the end of the row template | |
1744 * Parameters: | |
1745 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */ | |
1746 NK_API void nk_layout_row_template_end(struct nk_context*); | |
1747 /* nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size. | |
1748 * Parameters: | |
1749 * @ctx must point to an previously initialized `nk_context` struct | |
1750 * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns | |
1751 * @row_height holds height of each widget in row or zero for auto layouting | |
1752 * @widget_count number of widgets inside row */ | |
1753 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); | |
1754 /* nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio | |
1755 * Parameters: | |
1756 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` | |
1757 * @bounds position and size in laoyut space local coordinates */ | |
1758 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect); | |
1759 /* nk_layout_space_end - marks the end of the layout space | |
1760 * Parameters: | |
1761 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */ | |
1762 NK_API void nk_layout_space_end(struct nk_context*); | |
1763 /* nk_layout_space_bounds - returns total space allocated for `nk_layout_space` | |
1764 * Parameters: | |
1765 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */ | |
1766 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); | |
1767 /* nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space | |
1768 * Parameters: | |
1769 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` | |
1770 * @vec position to convert from layout space into screen coordinate space */ | |
1771 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); | |
1772 /* nk_layout_space_to_screen - converts vector from layout space into screen space | |
1773 * Parameters: | |
1774 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` | |
1775 * @vec position to convert from screen space into layout coordinate space */ | |
1776 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); | |
1777 /* nk_layout_space_rect_to_screen - converts rectangle from screen space into layout space | |
1778 * Parameters: | |
1779 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` | |
1780 * @bounds rectangle to convert from layout space into screen space */ | |
1781 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); | |
1782 /* nk_layout_space_rect_to_local - converts rectangle from layout space into screen space | |
1783 * Parameters: | |
1784 * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` | |
1785 * @bounds rectangle to convert from screen space into layout space */ | |
1786 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); | |
1787 /* ============================================================================= | |
1788 * | |
1789 * GROUP | |
1790 * | |
1791 * ============================================================================= */ | |
1792 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags); | |
1793 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags); | |
1794 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags); | |
1795 NK_API void nk_group_scrolled_end(struct nk_context*); | |
1796 NK_API void nk_group_end(struct nk_context*); | |
1797 /* ============================================================================= | |
1798 * | |
1799 * LIST VIEW | |
1800 * | |
1801 * ============================================================================= */ | |
1802 struct nk_list_view { | |
1803 /* public: */ | |
1804 int begin, end, count; | |
1805 /* private: */ | |
1806 int total_height; | |
1807 struct nk_context *ctx; | |
1808 nk_uint *scroll_pointer; | |
1809 nk_uint scroll_value; | |
1810 }; | |
1811 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count); | |
1812 NK_API void nk_list_view_end(struct nk_list_view*); | |
1813 /* ============================================================================= | |
1814 * | |
1815 * TREE | |
1816 * | |
1817 * ============================================================================= */ | |
1818 #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__) | |
1819 #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) | |
1820 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); | |
1821 #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__) | |
1822 #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) | |
1823 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); | |
1824 NK_API void nk_tree_pop(struct nk_context*); | |
1825 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); | |
1826 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); | |
1827 NK_API void nk_tree_state_pop(struct nk_context*); | |
1828 /* ============================================================================= | |
1829 * | |
1830 * WIDGET | |
1831 * | |
1832 * ============================================================================= */ | |
1833 enum nk_widget_layout_states { | |
1834 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ | |
1835 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ | |
1836 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ | |
1837 }; | |
1838 enum nk_widget_states { | |
1839 NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), | |
1840 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ | |
1841 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ | |
1842 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ | |
1843 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ | |
1844 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ | |
1845 NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ | |
1846 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ | |
1847 }; | |
1848 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); | |
1849 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); | |
1850 NK_API struct nk_rect nk_widget_bounds(struct nk_context*); | |
1851 NK_API struct nk_vec2 nk_widget_position(struct nk_context*); | |
1852 NK_API struct nk_vec2 nk_widget_size(struct nk_context*); | |
1853 NK_API float nk_widget_width(struct nk_context*); | |
1854 NK_API float nk_widget_height(struct nk_context*); | |
1855 NK_API int nk_widget_is_hovered(struct nk_context*); | |
1856 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); | |
1857 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down); | |
1858 NK_API void nk_spacing(struct nk_context*, int cols); | |
1859 /* ============================================================================= | |
1860 * | |
1861 * TEXT | |
1862 * | |
1863 * ============================================================================= */ | |
1864 enum nk_text_align { | |
1865 NK_TEXT_ALIGN_LEFT = 0x01, | |
1866 NK_TEXT_ALIGN_CENTERED = 0x02, | |
1867 NK_TEXT_ALIGN_RIGHT = 0x04, | |
1868 NK_TEXT_ALIGN_TOP = 0x08, | |
1869 NK_TEXT_ALIGN_MIDDLE = 0x10, | |
1870 NK_TEXT_ALIGN_BOTTOM = 0x20 | |
1871 }; | |
1872 enum nk_text_alignment { | |
1873 NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, | |
1874 NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, | |
1875 NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT | |
1876 }; | |
1877 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); | |
1878 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); | |
1879 NK_API void nk_text_wrap(struct nk_context*, const char*, int); | |
1880 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); | |
1881 NK_API void nk_label(struct nk_context*, const char*, nk_flags align); | |
1882 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); | |
1883 NK_API void nk_label_wrap(struct nk_context*, const char*); | |
1884 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); | |
1885 NK_API void nk_image(struct nk_context*, struct nk_image); | |
1886 #ifdef NK_INCLUDE_STANDARD_VARARGS | |
1887 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...); | |
1888 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...); | |
1889 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...); | |
1890 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...); | |
1891 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); | |
1892 NK_API void nk_value_int(struct nk_context*, const char *prefix, int); | |
1893 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); | |
1894 NK_API void nk_value_float(struct nk_context*, const char *prefix, float); | |
1895 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); | |
1896 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); | |
1897 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); | |
1898 #endif | |
1899 /* ============================================================================= | |
1900 * | |
1901 * BUTTON | |
1902 * | |
1903 * ============================================================================= */ | |
1904 NK_API int nk_button_text(struct nk_context*, const char *title, int len); | |
1905 NK_API int nk_button_label(struct nk_context*, const char *title); | |
1906 NK_API int nk_button_color(struct nk_context*, struct nk_color); | |
1907 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type); | |
1908 NK_API int nk_button_image(struct nk_context*, struct nk_image img); | |
1909 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); | |
1910 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); | |
1911 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); | |
1912 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); | |
1913 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); | |
1914 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); | |
1915 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); | |
1916 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); | |
1917 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment); | |
1918 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align); | |
1919 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment); | |
1920 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment); | |
1921 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); | |
1922 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); | |
1923 NK_API int nk_button_pop_behavior(struct nk_context*); | |
1924 /* ============================================================================= | |
1925 * | |
1926 * CHECKBOX | |
1927 * | |
1928 * ============================================================================= */ | |
1929 NK_API int nk_check_label(struct nk_context*, const char*, int active); | |
1930 NK_API int nk_check_text(struct nk_context*, const char*, int,int active); | |
1931 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); | |
1932 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); | |
1933 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active); | |
1934 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active); | |
1935 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); | |
1936 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); | |
1937 /* ============================================================================= | |
1938 * | |
1939 * RADIO BUTTON | |
1940 * | |
1941 * ============================================================================= */ | |
1942 NK_API int nk_radio_label(struct nk_context*, const char*, int *active); | |
1943 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active); | |
1944 NK_API int nk_option_label(struct nk_context*, const char*, int active); | |
1945 NK_API int nk_option_text(struct nk_context*, const char*, int, int active); | |
1946 /* ============================================================================= | |
1947 * | |
1948 * SELECTABLE | |
1949 * | |
1950 * ============================================================================= */ | |
1951 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value); | |
1952 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value); | |
1953 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value); | |
1954 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value); | |
1955 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value); | |
1956 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value); | |
1957 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value); | |
1958 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value); | |
1959 /* ============================================================================= | |
1960 * | |
1961 * SLIDER | |
1962 * | |
1963 * ============================================================================= */ | |
1964 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); | |
1965 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); | |
1966 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step); | |
1967 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step); | |
1968 /* ============================================================================= | |
1969 * | |
1970 * PROGRESSBAR | |
1971 * | |
1972 * ============================================================================= */ | |
1973 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable); | |
1974 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable); | |
1975 | |
1976 /* ============================================================================= | |
1977 * | |
1978 * COLOR PICKER | |
1979 * | |
1980 * ============================================================================= */ | |
1981 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format); | |
1982 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format); | |
1983 /* ============================================================================= | |
1984 * | |
1985 * PROPERTIES | |
1986 * | |
1987 * ============================================================================= */ | |
1988 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); | |
1989 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); | |
1990 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); | |
1991 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); | |
1992 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); | |
1993 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); | |
1994 /* ============================================================================= | |
1995 * | |
1996 * TEXT EDIT | |
1997 * | |
1998 * ============================================================================= */ | |
1999 enum nk_edit_flags { | |
2000 NK_EDIT_DEFAULT = 0, | |
2001 NK_EDIT_READ_ONLY = NK_FLAG(0), | |
2002 NK_EDIT_AUTO_SELECT = NK_FLAG(1), | |
2003 NK_EDIT_SIG_ENTER = NK_FLAG(2), | |
2004 NK_EDIT_ALLOW_TAB = NK_FLAG(3), | |
2005 NK_EDIT_NO_CURSOR = NK_FLAG(4), | |
2006 NK_EDIT_SELECTABLE = NK_FLAG(5), | |
2007 NK_EDIT_CLIPBOARD = NK_FLAG(6), | |
2008 NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), | |
2009 NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), | |
2010 NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), | |
2011 NK_EDIT_MULTILINE = NK_FLAG(10), | |
2012 NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11) | |
2013 }; | |
2014 enum nk_edit_types { | |
2015 NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, | |
2016 NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, | |
2017 NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, | |
2018 NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD | |
2019 }; | |
2020 enum nk_edit_events { | |
2021 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ | |
2022 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ | |
2023 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ | |
2024 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ | |
2025 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ | |
2026 }; | |
2027 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); | |
2028 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); | |
2029 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); | |
2030 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags); | |
2031 NK_API void nk_edit_unfocus(struct nk_context*); | |
2032 /* ============================================================================= | |
2033 * | |
2034 * CHART | |
2035 * | |
2036 * ============================================================================= */ | |
2037 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); | |
2038 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max); | |
2039 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); | |
2040 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value); | |
2041 NK_API nk_flags nk_chart_push(struct nk_context*, float); | |
2042 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); | |
2043 NK_API void nk_chart_end(struct nk_context*); | |
2044 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); | |
2045 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset); | |
2046 /* ============================================================================= | |
2047 * | |
2048 * POPUP | |
2049 * | |
2050 * ============================================================================= */ | |
2051 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); | |
2052 NK_API void nk_popup_close(struct nk_context*); | |
2053 NK_API void nk_popup_end(struct nk_context*); | |
2054 /* ============================================================================= | |
2055 * | |
2056 * COMBOBOX | |
2057 * | |
2058 * ============================================================================= */ | |
2059 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); | |
2060 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size); | |
2061 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size); | |
2062 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size); | |
2063 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); | |
2064 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size); | |
2065 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size); | |
2066 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size); | |
2067 /* ============================================================================= | |
2068 * | |
2069 * ABSTRACT COMBOBOX | |
2070 * | |
2071 * ============================================================================= */ | |
2072 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); | |
2073 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); | |
2074 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); | |
2075 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); | |
2076 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); | |
2077 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); | |
2078 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); | |
2079 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); | |
2080 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); | |
2081 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); | |
2082 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); | |
2083 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); | |
2084 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); | |
2085 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); | |
2086 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); | |
2087 NK_API void nk_combo_close(struct nk_context*); | |
2088 NK_API void nk_combo_end(struct nk_context*); | |
2089 /* ============================================================================= | |
2090 * | |
2091 * CONTEXTUAL | |
2092 * | |
2093 * ============================================================================= */ | |
2094 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); | |
2095 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); | |
2096 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); | |
2097 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); | |
2098 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); | |
2099 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); | |
2100 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); | |
2101 NK_API void nk_contextual_close(struct nk_context*); | |
2102 NK_API void nk_contextual_end(struct nk_context*); | |
2103 /* ============================================================================= | |
2104 * | |
2105 * TOOLTIP | |
2106 * | |
2107 * ============================================================================= */ | |
2108 NK_API void nk_tooltip(struct nk_context*, const char*); | |
2109 NK_API int nk_tooltip_begin(struct nk_context*, float width); | |
2110 NK_API void nk_tooltip_end(struct nk_context*); | |
2111 /* ============================================================================= | |
2112 * | |
2113 * MENU | |
2114 * | |
2115 * ============================================================================= */ | |
2116 NK_API void nk_menubar_begin(struct nk_context*); | |
2117 NK_API void nk_menubar_end(struct nk_context*); | |
2118 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); | |
2119 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); | |
2120 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); | |
2121 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); | |
2122 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); | |
2123 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); | |
2124 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size); | |
2125 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); | |
2126 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); | |
2127 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); | |
2128 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); | |
2129 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); | |
2130 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); | |
2131 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); | |
2132 NK_API void nk_menu_close(struct nk_context*); | |
2133 NK_API void nk_menu_end(struct nk_context*); | |
2134 /* ============================================================================= | |
2135 * | |
2136 * STYLE | |
2137 * | |
2138 * ============================================================================= */ | |
2139 enum nk_style_colors { | |
2140 NK_COLOR_TEXT, | |
2141 NK_COLOR_WINDOW, | |
2142 NK_COLOR_HEADER, | |
2143 NK_COLOR_BORDER, | |
2144 NK_COLOR_BUTTON, | |
2145 NK_COLOR_BUTTON_HOVER, | |
2146 NK_COLOR_BUTTON_ACTIVE, | |
2147 NK_COLOR_TOGGLE, | |
2148 NK_COLOR_TOGGLE_HOVER, | |
2149 NK_COLOR_TOGGLE_CURSOR, | |
2150 NK_COLOR_SELECT, | |
2151 NK_COLOR_SELECT_ACTIVE, | |
2152 NK_COLOR_SLIDER, | |
2153 NK_COLOR_SLIDER_CURSOR, | |
2154 NK_COLOR_SLIDER_CURSOR_HOVER, | |
2155 NK_COLOR_SLIDER_CURSOR_ACTIVE, | |
2156 NK_COLOR_PROPERTY, | |
2157 NK_COLOR_EDIT, | |
2158 NK_COLOR_EDIT_CURSOR, | |
2159 NK_COLOR_COMBO, | |
2160 NK_COLOR_CHART, | |
2161 NK_COLOR_CHART_COLOR, | |
2162 NK_COLOR_CHART_COLOR_HIGHLIGHT, | |
2163 NK_COLOR_SCROLLBAR, | |
2164 NK_COLOR_SCROLLBAR_CURSOR, | |
2165 NK_COLOR_SCROLLBAR_CURSOR_HOVER, | |
2166 NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, | |
2167 NK_COLOR_TAB_HEADER, | |
2168 NK_COLOR_COUNT | |
2169 }; | |
2170 enum nk_style_cursor { | |
2171 NK_CURSOR_ARROW, | |
2172 NK_CURSOR_TEXT, | |
2173 NK_CURSOR_MOVE, | |
2174 NK_CURSOR_RESIZE_VERTICAL, | |
2175 NK_CURSOR_RESIZE_HORIZONTAL, | |
2176 NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, | |
2177 NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, | |
2178 NK_CURSOR_COUNT | |
2179 }; | |
2180 NK_API void nk_style_default(struct nk_context*); | |
2181 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); | |
2182 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); | |
2183 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); | |
2184 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); | |
2185 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); | |
2186 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); | |
2187 NK_API void nk_style_show_cursor(struct nk_context*); | |
2188 NK_API void nk_style_hide_cursor(struct nk_context*); | |
2189 | |
2190 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*); | |
2191 NK_API int nk_style_push_float(struct nk_context*, float*, float); | |
2192 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); | |
2193 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); | |
2194 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); | |
2195 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); | |
2196 | |
2197 NK_API int nk_style_pop_font(struct nk_context*); | |
2198 NK_API int nk_style_pop_float(struct nk_context*); | |
2199 NK_API int nk_style_pop_vec2(struct nk_context*); | |
2200 NK_API int nk_style_pop_style_item(struct nk_context*); | |
2201 NK_API int nk_style_pop_flags(struct nk_context*); | |
2202 NK_API int nk_style_pop_color(struct nk_context*); | |
2203 /* ============================================================================= | |
2204 * | |
2205 * COLOR | |
2206 * | |
2207 * ============================================================================= */ | |
2208 NK_API struct nk_color nk_rgb(int r, int g, int b); | |
2209 NK_API struct nk_color nk_rgb_iv(const int *rgb); | |
2210 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); | |
2211 NK_API struct nk_color nk_rgb_f(float r, float g, float b); | |
2212 NK_API struct nk_color nk_rgb_fv(const float *rgb); | |
2213 NK_API struct nk_color nk_rgb_hex(const char *rgb); | |
2214 | |
2215 NK_API struct nk_color nk_rgba(int r, int g, int b, int a); | |
2216 NK_API struct nk_color nk_rgba_u32(nk_uint); | |
2217 NK_API struct nk_color nk_rgba_iv(const int *rgba); | |
2218 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); | |
2219 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); | |
2220 NK_API struct nk_color nk_rgba_fv(const float *rgba); | |
2221 NK_API struct nk_color nk_rgba_hex(const char *rgb); | |
2222 | |
2223 NK_API struct nk_color nk_hsv(int h, int s, int v); | |
2224 NK_API struct nk_color nk_hsv_iv(const int *hsv); | |
2225 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); | |
2226 NK_API struct nk_color nk_hsv_f(float h, float s, float v); | |
2227 NK_API struct nk_color nk_hsv_fv(const float *hsv); | |
2228 | |
2229 NK_API struct nk_color nk_hsva(int h, int s, int v, int a); | |
2230 NK_API struct nk_color nk_hsva_iv(const int *hsva); | |
2231 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); | |
2232 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); | |
2233 NK_API struct nk_color nk_hsva_fv(const float *hsva); | |
2234 | |
2235 /* color (conversion nuklear --> user) */ | |
2236 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); | |
2237 NK_API void nk_color_fv(float *rgba_out, struct nk_color); | |
2238 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); | |
2239 NK_API void nk_color_dv(double *rgba_out, struct nk_color); | |
2240 | |
2241 NK_API nk_uint nk_color_u32(struct nk_color); | |
2242 NK_API void nk_color_hex_rgba(char *output, struct nk_color); | |
2243 NK_API void nk_color_hex_rgb(char *output, struct nk_color); | |
2244 | |
2245 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); | |
2246 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); | |
2247 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); | |
2248 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); | |
2249 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); | |
2250 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); | |
2251 | |
2252 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); | |
2253 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); | |
2254 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); | |
2255 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); | |
2256 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); | |
2257 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); | |
2258 /* ============================================================================= | |
2259 * | |
2260 * IMAGE | |
2261 * | |
2262 * ============================================================================= */ | |
2263 NK_API nk_handle nk_handle_ptr(void*); | |
2264 NK_API nk_handle nk_handle_id(int); | |
2265 NK_API struct nk_image nk_image_handle(nk_handle); | |
2266 NK_API struct nk_image nk_image_ptr(void*); | |
2267 NK_API struct nk_image nk_image_id(int); | |
2268 NK_API int nk_image_is_subimage(const struct nk_image* img); | |
2269 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region); | |
2270 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region); | |
2271 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region); | |
2272 /* ============================================================================= | |
2273 * | |
2274 * MATH | |
2275 * | |
2276 * ============================================================================= */ | |
2277 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); | |
2278 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); | |
2279 | |
2280 NK_API struct nk_vec2 nk_vec2(float x, float y); | |
2281 NK_API struct nk_vec2 nk_vec2i(int x, int y); | |
2282 NK_API struct nk_vec2 nk_vec2v(const float *xy); | |
2283 NK_API struct nk_vec2 nk_vec2iv(const int *xy); | |
2284 | |
2285 NK_API struct nk_rect nk_get_null_rect(void); | |
2286 NK_API struct nk_rect nk_rect(float x, float y, float w, float h); | |
2287 NK_API struct nk_rect nk_recti(int x, int y, int w, int h); | |
2288 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); | |
2289 NK_API struct nk_rect nk_rectv(const float *xywh); | |
2290 NK_API struct nk_rect nk_rectiv(const int *xywh); | |
2291 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); | |
2292 NK_API struct nk_vec2 nk_rect_size(struct nk_rect); | |
2293 /* ============================================================================= | |
2294 * | |
2295 * STRING | |
2296 * | |
2297 * ============================================================================= */ | |
2298 NK_API int nk_strlen(const char *str); | |
2299 NK_API int nk_stricmp(const char *s1, const char *s2); | |
2300 NK_API int nk_stricmpn(const char *s1, const char *s2, int n); | |
2301 NK_API int nk_strtoi(const char *str, const char **endptr); | |
2302 NK_API float nk_strtof(const char *str, const char **endptr); | |
2303 NK_API double nk_strtod(const char *str, const char **endptr); | |
2304 NK_API int nk_strfilter(const char *text, const char *regexp); | |
2305 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); | |
2306 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); | |
2307 /* ============================================================================= | |
2308 * | |
2309 * UTF-8 | |
2310 * | |
2311 * ============================================================================= */ | |
2312 NK_API int nk_utf_decode(const char*, nk_rune*, int); | |
2313 NK_API int nk_utf_encode(nk_rune, char*, int); | |
2314 NK_API int nk_utf_len(const char*, int byte_len); | |
2315 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); | |
2316 /* =============================================================== | |
2317 * | |
2318 * FONT | |
2319 * | |
2320 * ===============================================================*/ | |
2321 /* Font handling in this library was designed to be quite customizable and lets | |
2322 you decide what you want to use and what you want to provide. There are three | |
2323 different ways to use the font atlas. The first two will use your font | |
2324 handling scheme and only requires essential data to run nuklear. The next | |
2325 slightly more advanced features is font handling with vertex buffer output. | |
2326 Finally the most complex API wise is using nuklear's font baking API. | |
2327 | |
2328 1.) Using your own implementation without vertex buffer output | |
2329 -------------------------------------------------------------- | |
2330 So first up the easiest way to do font handling is by just providing a | |
2331 `nk_user_font` struct which only requires the height in pixel of the used | |
2332 font and a callback to calculate the width of a string. This way of handling | |
2333 fonts is best fitted for using the normal draw shape command API where you | |
2334 do all the text drawing yourself and the library does not require any kind | |
2335 of deeper knowledge about which font handling mechanism you use. | |
2336 IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist | |
2337 over the complete life time! I know this sucks but it is currently the only | |
2338 way to switch between fonts. | |
2339 | |
2340 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) | |
2341 { | |
2342 your_font_type *type = handle.ptr; | |
2343 float text_width = ...; | |
2344 return text_width; | |
2345 } | |
2346 | |
2347 struct nk_user_font font; | |
2348 font.userdata.ptr = &your_font_class_or_struct; | |
2349 font.height = your_font_height; | |
2350 font.width = your_text_width_calculation; | |
2351 | |
2352 struct nk_context ctx; | |
2353 nk_init_default(&ctx, &font); | |
2354 | |
2355 2.) Using your own implementation with vertex buffer output | |
2356 -------------------------------------------------------------- | |
2357 While the first approach works fine if you don't want to use the optional | |
2358 vertex buffer output it is not enough if you do. To get font handling working | |
2359 for these cases you have to provide two additional parameters inside the | |
2360 `nk_user_font`. First a texture atlas handle used to draw text as subimages | |
2361 of a bigger font atlas texture and a callback to query a character's glyph | |
2362 information (offset, size, ...). So it is still possible to provide your own | |
2363 font and use the vertex buffer output. | |
2364 | |
2365 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) | |
2366 { | |
2367 your_font_type *type = handle.ptr; | |
2368 float text_width = ...; | |
2369 return text_width; | |
2370 } | |
2371 void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) | |
2372 { | |
2373 your_font_type *type = handle.ptr; | |
2374 glyph.width = ...; | |
2375 glyph.height = ...; | |
2376 glyph.xadvance = ...; | |
2377 glyph.uv[0].x = ...; | |
2378 glyph.uv[0].y = ...; | |
2379 glyph.uv[1].x = ...; | |
2380 glyph.uv[1].y = ...; | |
2381 glyph.offset.x = ...; | |
2382 glyph.offset.y = ...; | |
2383 } | |
2384 | |
2385 struct nk_user_font font; | |
2386 font.userdata.ptr = &your_font_class_or_struct; | |
2387 font.height = your_font_height; | |
2388 font.width = your_text_width_calculation; | |
2389 font.query = query_your_font_glyph; | |
2390 font.texture.id = your_font_texture; | |
2391 | |
2392 struct nk_context ctx; | |
2393 nk_init_default(&ctx, &font); | |
2394 | |
2395 3.) Nuklear font baker | |
2396 ------------------------------------ | |
2397 The final approach if you do not have a font handling functionality or don't | |
2398 want to use it in this library is by using the optional font baker. | |
2399 The font baker APIs can be used to create a font plus font atlas texture | |
2400 and can be used with or without the vertex buffer output. | |
2401 | |
2402 It still uses the `nk_user_font` struct and the two different approaches | |
2403 previously stated still work. The font baker is not located inside | |
2404 `nk_context` like all other systems since it can be understood as more of | |
2405 an extension to nuklear and does not really depend on any `nk_context` state. | |
2406 | |
2407 Font baker need to be initialized first by one of the nk_font_atlas_init_xxx | |
2408 functions. If you don't care about memory just call the default version | |
2409 `nk_font_atlas_init_default` which will allocate all memory from the standard library. | |
2410 If you want to control memory allocation but you don't care if the allocated | |
2411 memory is temporary and therefore can be freed directly after the baking process | |
2412 is over or permanent you can call `nk_font_atlas_init`. | |
2413 | |
2414 After successfully initializing the font baker you can add Truetype(.ttf) fonts from | |
2415 different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. | |
2416 functions. Adding font will permanently store each font, font config and ttf memory block(!) | |
2417 inside the font atlas and allows to reuse the font atlas. If you don't want to reuse | |
2418 the font baker by for example adding additional fonts you can call | |
2419 `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). | |
2420 | |
2421 As soon as you added all fonts you wanted you can now start the baking process | |
2422 for every selected glyph to image by calling `nk_font_atlas_bake`. | |
2423 The baking process returns image memory, width and height which can be used to | |
2424 either create your own image object or upload it to any graphics library. | |
2425 No matter which case you finally have to call `nk_font_atlas_end` which | |
2426 will free all temporary memory including the font atlas image so make sure | |
2427 you created our texture beforehand. `nk_font_atlas_end` requires a handle | |
2428 to your font texture or object and optionally fills a `struct nk_draw_null_texture` | |
2429 which can be used for the optional vertex output. If you don't want it just | |
2430 set the argument to `NULL`. | |
2431 | |
2432 At this point you are done and if you don't want to reuse the font atlas you | |
2433 can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration | |
2434 memory. Finally if you don't use the font atlas and any of it's fonts anymore | |
2435 you need to call `nk_font_atlas_clear` to free all memory still being used. | |
2436 | |
2437 struct nk_font_atlas atlas; | |
2438 nk_font_atlas_init_default(&atlas); | |
2439 nk_font_atlas_begin(&atlas); | |
2440 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); | |
2441 nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); | |
2442 const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32); | |
2443 nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); | |
2444 | |
2445 struct nk_context ctx; | |
2446 nk_init_default(&ctx, &font->handle); | |
2447 while (1) { | |
2448 | |
2449 } | |
2450 nk_font_atlas_clear(&atlas); | |
2451 | |
2452 The font baker API is probably the most complex API inside this library and | |
2453 I would suggest reading some of my examples `example/` to get a grip on how | |
2454 to use the font atlas. There are a number of details I left out. For example | |
2455 how to merge fonts, configure a font with `nk_font_config` to use other languages, | |
2456 use another texture coordinate format and a lot more: | |
2457 | |
2458 struct nk_font_config cfg = nk_font_config(font_pixel_height); | |
2459 cfg.merge_mode = nk_false or nk_true; | |
2460 cfg.range = nk_font_korean_glyph_ranges(); | |
2461 cfg.coord_type = NK_COORD_PIXEL; | |
2462 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); | |
2463 | |
2464 */ | |
2465 struct nk_user_font_glyph; | |
2466 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); | |
2467 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, | |
2468 struct nk_user_font_glyph *glyph, | |
2469 nk_rune codepoint, nk_rune next_codepoint); | |
2470 | |
2471 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT) | |
2472 struct nk_user_font_glyph { | |
2473 struct nk_vec2 uv[2]; | |
2474 /* texture coordinates */ | |
2475 struct nk_vec2 offset; | |
2476 /* offset between top left and glyph */ | |
2477 float width, height; | |
2478 /* size of the glyph */ | |
2479 float xadvance; | |
2480 /* offset to the next glyph */ | |
2481 }; | |
2482 #endif | |
2483 | |
2484 struct nk_user_font { | |
2485 nk_handle userdata; | |
2486 /* user provided font handle */ | |
2487 float height; | |
2488 /* max height of the font */ | |
2489 nk_text_width_f width; | |
2490 /* font string width in pixel callback */ | |
2491 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
2492 nk_query_font_glyph_f query; | |
2493 /* font glyph callback to query drawing info */ | |
2494 nk_handle texture; | |
2495 /* texture handle to the used font atlas or texture */ | |
2496 #endif | |
2497 }; | |
2498 | |
2499 #ifdef NK_INCLUDE_FONT_BAKING | |
2500 enum nk_font_coord_type { | |
2501 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ | |
2502 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ | |
2503 }; | |
2504 | |
2505 struct nk_baked_font { | |
2506 float height; | |
2507 /* height of the font */ | |
2508 float ascent, descent; | |
2509 /* font glyphs ascent and descent */ | |
2510 nk_rune glyph_offset; | |
2511 /* glyph array offset inside the font glyph baking output array */ | |
2512 nk_rune glyph_count; | |
2513 /* number of glyphs of this font inside the glyph baking array output */ | |
2514 const nk_rune *ranges; | |
2515 /* font codepoint ranges as pairs of (from/to) and 0 as last element */ | |
2516 }; | |
2517 | |
2518 struct nk_font_config { | |
2519 struct nk_font_config *next; | |
2520 /* NOTE: only used internally */ | |
2521 void *ttf_blob; | |
2522 /* pointer to loaded TTF file memory block. | |
2523 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ | |
2524 nk_size ttf_size; | |
2525 /* size of the loaded TTF file memory block | |
2526 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ | |
2527 | |
2528 unsigned char ttf_data_owned_by_atlas; | |
2529 /* used inside font atlas: default to: 0*/ | |
2530 unsigned char merge_mode; | |
2531 /* merges this font into the last font */ | |
2532 unsigned char pixel_snap; | |
2533 /* align every character to pixel boundary (if true set oversample (1,1)) */ | |
2534 unsigned char oversample_v, oversample_h; | |
2535 /* rasterize at hight quality for sub-pixel position */ | |
2536 unsigned char padding[3]; | |
2537 | |
2538 float size; | |
2539 /* baked pixel height of the font */ | |
2540 enum nk_font_coord_type coord_type; | |
2541 /* texture coordinate format with either pixel or UV coordinates */ | |
2542 struct nk_vec2 spacing; | |
2543 /* extra pixel spacing between glyphs */ | |
2544 const nk_rune *range; | |
2545 /* list of unicode ranges (2 values per range, zero terminated) */ | |
2546 struct nk_baked_font *font; | |
2547 /* font to setup in the baking process: NOTE: not needed for font atlas */ | |
2548 nk_rune fallback_glyph; | |
2549 /* fallback glyph to use if a given rune is not found */ | |
2550 }; | |
2551 | |
2552 struct nk_font_glyph { | |
2553 nk_rune codepoint; | |
2554 float xadvance; | |
2555 float x0, y0, x1, y1, w, h; | |
2556 float u0, v0, u1, v1; | |
2557 }; | |
2558 | |
2559 struct nk_font { | |
2560 struct nk_font *next; | |
2561 struct nk_user_font handle; | |
2562 struct nk_baked_font info; | |
2563 float scale; | |
2564 struct nk_font_glyph *glyphs; | |
2565 const struct nk_font_glyph *fallback; | |
2566 nk_rune fallback_codepoint; | |
2567 nk_handle texture; | |
2568 struct nk_font_config *config; | |
2569 }; | |
2570 | |
2571 enum nk_font_atlas_format { | |
2572 NK_FONT_ATLAS_ALPHA8, | |
2573 NK_FONT_ATLAS_RGBA32 | |
2574 }; | |
2575 | |
2576 struct nk_font_atlas { | |
2577 void *pixel; | |
2578 int tex_width; | |
2579 int tex_height; | |
2580 | |
2581 struct nk_allocator permanent; | |
2582 struct nk_allocator temporary; | |
2583 | |
2584 struct nk_recti custom; | |
2585 struct nk_cursor cursors[NK_CURSOR_COUNT]; | |
2586 | |
2587 int glyph_count; | |
2588 struct nk_font_glyph *glyphs; | |
2589 struct nk_font *default_font; | |
2590 struct nk_font *fonts; | |
2591 struct nk_font_config *config; | |
2592 int font_num; | |
2593 }; | |
2594 | |
2595 /* some language glyph codepoint ranges */ | |
2596 NK_API const nk_rune *nk_font_default_glyph_ranges(void); | |
2597 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); | |
2598 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); | |
2599 NK_API const nk_rune *nk_font_korean_glyph_ranges(void); | |
2600 | |
2601 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
2602 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); | |
2603 #endif | |
2604 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); | |
2605 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); | |
2606 NK_API void nk_font_atlas_begin(struct nk_font_atlas*); | |
2607 NK_API struct nk_font_config nk_font_config(float pixel_height); | |
2608 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); | |
2609 #ifdef NK_INCLUDE_DEFAULT_FONT | |
2610 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); | |
2611 #endif | |
2612 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config); | |
2613 #ifdef NK_INCLUDE_STANDARD_IO | |
2614 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*); | |
2615 #endif | |
2616 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*); | |
2617 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config); | |
2618 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); | |
2619 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); | |
2620 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); | |
2621 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); | |
2622 NK_API void nk_font_atlas_clear(struct nk_font_atlas*); | |
2623 | |
2624 #endif | |
2625 | |
2626 /* ============================================================== | |
2627 * | |
2628 * MEMORY BUFFER | |
2629 * | |
2630 * ===============================================================*/ | |
2631 /* A basic (double)-buffer with linear allocation and resetting as only | |
2632 freeing policy. The buffer's main purpose is to control all memory management | |
2633 inside the GUI toolkit and still leave memory control as much as possible in | |
2634 the hand of the user while also making sure the library is easy to use if | |
2635 not as much control is needed. | |
2636 In general all memory inside this library can be provided from the user in | |
2637 three different ways. | |
2638 | |
2639 The first way and the one providing most control is by just passing a fixed | |
2640 size memory block. In this case all control lies in the hand of the user | |
2641 since he can exactly control where the memory comes from and how much memory | |
2642 the library should consume. Of course using the fixed size API removes the | |
2643 ability to automatically resize a buffer if not enough memory is provided so | |
2644 you have to take over the resizing. While being a fixed sized buffer sounds | |
2645 quite limiting, it is very effective in this library since the actual memory | |
2646 consumption is quite stable and has a fixed upper bound for a lot of cases. | |
2647 | |
2648 If you don't want to think about how much memory the library should allocate | |
2649 at all time or have a very dynamic UI with unpredictable memory consumption | |
2650 habits but still want control over memory allocation you can use the dynamic | |
2651 allocator based API. The allocator consists of two callbacks for allocating | |
2652 and freeing memory and optional userdata so you can plugin your own allocator. | |
2653 | |
2654 The final and easiest way can be used by defining | |
2655 NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory | |
2656 allocation functions malloc and free and takes over complete control over | |
2657 memory in this library. | |
2658 */ | |
2659 struct nk_memory_status { | |
2660 void *memory; | |
2661 unsigned int type; | |
2662 nk_size size; | |
2663 nk_size allocated; | |
2664 nk_size needed; | |
2665 nk_size calls; | |
2666 }; | |
2667 | |
2668 enum nk_allocation_type { | |
2669 NK_BUFFER_FIXED, | |
2670 NK_BUFFER_DYNAMIC | |
2671 }; | |
2672 | |
2673 enum nk_buffer_allocation_type { | |
2674 NK_BUFFER_FRONT, | |
2675 NK_BUFFER_BACK, | |
2676 NK_BUFFER_MAX | |
2677 }; | |
2678 | |
2679 struct nk_buffer_marker { | |
2680 int active; | |
2681 nk_size offset; | |
2682 }; | |
2683 | |
2684 struct nk_memory {void *ptr;nk_size size;}; | |
2685 struct nk_buffer { | |
2686 struct nk_buffer_marker marker[NK_BUFFER_MAX]; | |
2687 /* buffer marker to free a buffer to a certain offset */ | |
2688 struct nk_allocator pool; | |
2689 /* allocator callback for dynamic buffers */ | |
2690 enum nk_allocation_type type; | |
2691 /* memory management type */ | |
2692 struct nk_memory memory; | |
2693 /* memory and size of the current memory block */ | |
2694 float grow_factor; | |
2695 /* growing factor for dynamic memory management */ | |
2696 nk_size allocated; | |
2697 /* total amount of memory allocated */ | |
2698 nk_size needed; | |
2699 /* totally consumed memory given that enough memory is present */ | |
2700 nk_size calls; | |
2701 /* number of allocation calls */ | |
2702 nk_size size; | |
2703 /* current size of the buffer */ | |
2704 }; | |
2705 | |
2706 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
2707 NK_API void nk_buffer_init_default(struct nk_buffer*); | |
2708 #endif | |
2709 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); | |
2710 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); | |
2711 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); | |
2712 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); | |
2713 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); | |
2714 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); | |
2715 NK_API void nk_buffer_clear(struct nk_buffer*); | |
2716 NK_API void nk_buffer_free(struct nk_buffer*); | |
2717 NK_API void *nk_buffer_memory(struct nk_buffer*); | |
2718 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); | |
2719 NK_API nk_size nk_buffer_total(struct nk_buffer*); | |
2720 | |
2721 /* ============================================================== | |
2722 * | |
2723 * STRING | |
2724 * | |
2725 * ===============================================================*/ | |
2726 /* Basic string buffer which is only used in context with the text editor | |
2727 * to manage and manipulate dynamic or fixed size string content. This is _NOT_ | |
2728 * the default string handling method. The only instance you should have any contact | |
2729 * with this API is if you interact with an `nk_text_edit` object inside one of the | |
2730 * copy and paste functions and even there only for more advanced cases. */ | |
2731 struct nk_str { | |
2732 struct nk_buffer buffer; | |
2733 int len; /* in codepoints/runes/glyphs */ | |
2734 }; | |
2735 | |
2736 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
2737 NK_API void nk_str_init_default(struct nk_str*); | |
2738 #endif | |
2739 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); | |
2740 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); | |
2741 NK_API void nk_str_clear(struct nk_str*); | |
2742 NK_API void nk_str_free(struct nk_str*); | |
2743 | |
2744 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); | |
2745 NK_API int nk_str_append_str_char(struct nk_str*, const char*); | |
2746 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); | |
2747 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); | |
2748 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); | |
2749 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); | |
2750 | |
2751 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); | |
2752 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); | |
2753 | |
2754 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); | |
2755 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); | |
2756 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); | |
2757 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); | |
2758 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); | |
2759 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); | |
2760 | |
2761 NK_API void nk_str_remove_chars(struct nk_str*, int len); | |
2762 NK_API void nk_str_remove_runes(struct nk_str *str, int len); | |
2763 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); | |
2764 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); | |
2765 | |
2766 NK_API char *nk_str_at_char(struct nk_str*, int pos); | |
2767 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); | |
2768 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); | |
2769 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); | |
2770 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); | |
2771 | |
2772 NK_API char *nk_str_get(struct nk_str*); | |
2773 NK_API const char *nk_str_get_const(const struct nk_str*); | |
2774 NK_API int nk_str_len(struct nk_str*); | |
2775 NK_API int nk_str_len_char(struct nk_str*); | |
2776 | |
2777 /*=============================================================== | |
2778 * | |
2779 * TEXT EDITOR | |
2780 * | |
2781 * ===============================================================*/ | |
2782 /* Editing text in this library is handled by either `nk_edit_string` or | |
2783 * `nk_edit_buffer`. But like almost everything in this library there are multiple | |
2784 * ways of doing it and a balance between control and ease of use with memory | |
2785 * as well as functionality controlled by flags. | |
2786 * | |
2787 * This library generally allows three different levels of memory control: | |
2788 * First of is the most basic way of just providing a simple char array with | |
2789 * string length. This method is probably the easiest way of handling simple | |
2790 * user text input. Main upside is complete control over memory while the biggest | |
2791 * downside in comparison with the other two approaches is missing undo/redo. | |
2792 * | |
2793 * For UIs that require undo/redo the second way was created. It is based on | |
2794 * a fixed size nk_text_edit struct, which has an internal undo/redo stack. | |
2795 * This is mainly useful if you want something more like a text editor but don't want | |
2796 * to have a dynamically growing buffer. | |
2797 * | |
2798 * The final way is using a dynamically growing nk_text_edit struct, which | |
2799 * has both a default version if you don't care where memory comes from and an | |
2800 * allocator version if you do. While the text editor is quite powerful for its | |
2801 * complexity I would not recommend editing gigabytes of data with it. | |
2802 * It is rather designed for uses cases which make sense for a GUI library not for | |
2803 * an full blown text editor. | |
2804 */ | |
2805 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT | |
2806 #define NK_TEXTEDIT_UNDOSTATECOUNT 99 | |
2807 #endif | |
2808 | |
2809 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT | |
2810 #define NK_TEXTEDIT_UNDOCHARCOUNT 999 | |
2811 #endif | |
2812 | |
2813 struct nk_text_edit; | |
2814 struct nk_clipboard { | |
2815 nk_handle userdata; | |
2816 nk_plugin_paste paste; | |
2817 nk_plugin_copy copy; | |
2818 }; | |
2819 | |
2820 struct nk_text_undo_record { | |
2821 int where; | |
2822 short insert_length; | |
2823 short delete_length; | |
2824 short char_storage; | |
2825 }; | |
2826 | |
2827 struct nk_text_undo_state { | |
2828 struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; | |
2829 nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; | |
2830 short undo_point; | |
2831 short redo_point; | |
2832 short undo_char_point; | |
2833 short redo_char_point; | |
2834 }; | |
2835 | |
2836 enum nk_text_edit_type { | |
2837 NK_TEXT_EDIT_SINGLE_LINE, | |
2838 NK_TEXT_EDIT_MULTI_LINE | |
2839 }; | |
2840 | |
2841 enum nk_text_edit_mode { | |
2842 NK_TEXT_EDIT_MODE_VIEW, | |
2843 NK_TEXT_EDIT_MODE_INSERT, | |
2844 NK_TEXT_EDIT_MODE_REPLACE | |
2845 }; | |
2846 | |
2847 struct nk_text_edit { | |
2848 struct nk_clipboard clip; | |
2849 struct nk_str string; | |
2850 nk_plugin_filter filter; | |
2851 struct nk_vec2 scrollbar; | |
2852 | |
2853 int cursor; | |
2854 int select_start; | |
2855 int select_end; | |
2856 unsigned char mode; | |
2857 unsigned char cursor_at_end_of_line; | |
2858 unsigned char initialized; | |
2859 unsigned char has_preferred_x; | |
2860 unsigned char single_line; | |
2861 unsigned char active; | |
2862 unsigned char padding1; | |
2863 float preferred_x; | |
2864 struct nk_text_undo_state undo; | |
2865 }; | |
2866 | |
2867 /* filter function */ | |
2868 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode); | |
2869 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); | |
2870 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode); | |
2871 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); | |
2872 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); | |
2873 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); | |
2874 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); | |
2875 | |
2876 /* text editor */ | |
2877 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
2878 NK_API void nk_textedit_init_default(struct nk_text_edit*); | |
2879 #endif | |
2880 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); | |
2881 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); | |
2882 NK_API void nk_textedit_free(struct nk_text_edit*); | |
2883 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); | |
2884 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); | |
2885 NK_API void nk_textedit_delete_selection(struct nk_text_edit*); | |
2886 NK_API void nk_textedit_select_all(struct nk_text_edit*); | |
2887 NK_API int nk_textedit_cut(struct nk_text_edit*); | |
2888 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len); | |
2889 NK_API void nk_textedit_undo(struct nk_text_edit*); | |
2890 NK_API void nk_textedit_redo(struct nk_text_edit*); | |
2891 | |
2892 /* =============================================================== | |
2893 * | |
2894 * DRAWING | |
2895 * | |
2896 * ===============================================================*/ | |
2897 /* This library was designed to be render backend agnostic so it does | |
2898 not draw anything to screen. Instead all drawn shapes, widgets | |
2899 are made of, are buffered into memory and make up a command queue. | |
2900 Each frame therefore fills the command buffer with draw commands | |
2901 that then need to be executed by the user and his own render backend. | |
2902 After that the command buffer needs to be cleared and a new frame can be | |
2903 started. It is probably important to note that the command buffer is the main | |
2904 drawing API and the optional vertex buffer API only takes this format and | |
2905 converts it into a hardware accessible format. | |
2906 | |
2907 To use the command queue to draw your own widgets you can access the | |
2908 command buffer of each window by calling `nk_window_get_canvas` after | |
2909 previously having called `nk_begin`: | |
2910 | |
2911 void draw_red_rectangle_widget(struct nk_context *ctx) | |
2912 { | |
2913 struct nk_command_buffer *canvas; | |
2914 struct nk_input *input = &ctx->input; | |
2915 canvas = nk_window_get_canvas(ctx); | |
2916 | |
2917 struct nk_rect space; | |
2918 enum nk_widget_layout_states state; | |
2919 state = nk_widget(&space, ctx); | |
2920 if (!state) return; | |
2921 | |
2922 if (state != NK_WIDGET_ROM) | |
2923 update_your_widget_by_user_input(...); | |
2924 nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); | |
2925 } | |
2926 | |
2927 if (nk_begin(...)) { | |
2928 nk_layout_row_dynamic(ctx, 25, 1); | |
2929 draw_red_rectangle_widget(ctx); | |
2930 } | |
2931 nk_end(..) | |
2932 | |
2933 Important to know if you want to create your own widgets is the `nk_widget` | |
2934 call. It allocates space on the panel reserved for this widget to be used, | |
2935 but also returns the state of the widget space. If your widget is not seen and does | |
2936 not have to be updated it is '0' and you can just return. If it only has | |
2937 to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both | |
2938 update and draw your widget. The reason for separating is to only draw and | |
2939 update what is actually necessary which is crucial for performance. | |
2940 */ | |
2941 enum nk_command_type { | |
2942 NK_COMMAND_NOP, | |
2943 NK_COMMAND_SCISSOR, | |
2944 NK_COMMAND_LINE, | |
2945 NK_COMMAND_CURVE, | |
2946 NK_COMMAND_RECT, | |
2947 NK_COMMAND_RECT_FILLED, | |
2948 NK_COMMAND_RECT_MULTI_COLOR, | |
2949 NK_COMMAND_CIRCLE, | |
2950 NK_COMMAND_CIRCLE_FILLED, | |
2951 NK_COMMAND_ARC, | |
2952 NK_COMMAND_ARC_FILLED, | |
2953 NK_COMMAND_TRIANGLE, | |
2954 NK_COMMAND_TRIANGLE_FILLED, | |
2955 NK_COMMAND_POLYGON, | |
2956 NK_COMMAND_POLYGON_FILLED, | |
2957 NK_COMMAND_POLYLINE, | |
2958 NK_COMMAND_TEXT, | |
2959 NK_COMMAND_IMAGE, | |
2960 NK_COMMAND_CUSTOM | |
2961 }; | |
2962 | |
2963 /* command base and header of every command inside the buffer */ | |
2964 struct nk_command { | |
2965 enum nk_command_type type; | |
2966 nk_size next; | |
2967 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
2968 nk_handle userdata; | |
2969 #endif | |
2970 }; | |
2971 | |
2972 struct nk_command_scissor { | |
2973 struct nk_command header; | |
2974 short x, y; | |
2975 unsigned short w, h; | |
2976 }; | |
2977 | |
2978 struct nk_command_line { | |
2979 struct nk_command header; | |
2980 unsigned short line_thickness; | |
2981 struct nk_vec2i begin; | |
2982 struct nk_vec2i end; | |
2983 struct nk_color color; | |
2984 }; | |
2985 | |
2986 struct nk_command_curve { | |
2987 struct nk_command header; | |
2988 unsigned short line_thickness; | |
2989 struct nk_vec2i begin; | |
2990 struct nk_vec2i end; | |
2991 struct nk_vec2i ctrl[2]; | |
2992 struct nk_color color; | |
2993 }; | |
2994 | |
2995 struct nk_command_rect { | |
2996 struct nk_command header; | |
2997 unsigned short rounding; | |
2998 unsigned short line_thickness; | |
2999 short x, y; | |
3000 unsigned short w, h; | |
3001 struct nk_color color; | |
3002 }; | |
3003 | |
3004 struct nk_command_rect_filled { | |
3005 struct nk_command header; | |
3006 unsigned short rounding; | |
3007 short x, y; | |
3008 unsigned short w, h; | |
3009 struct nk_color color; | |
3010 }; | |
3011 | |
3012 struct nk_command_rect_multi_color { | |
3013 struct nk_command header; | |
3014 short x, y; | |
3015 unsigned short w, h; | |
3016 struct nk_color left; | |
3017 struct nk_color top; | |
3018 struct nk_color bottom; | |
3019 struct nk_color right; | |
3020 }; | |
3021 | |
3022 struct nk_command_triangle { | |
3023 struct nk_command header; | |
3024 unsigned short line_thickness; | |
3025 struct nk_vec2i a; | |
3026 struct nk_vec2i b; | |
3027 struct nk_vec2i c; | |
3028 struct nk_color color; | |
3029 }; | |
3030 | |
3031 struct nk_command_triangle_filled { | |
3032 struct nk_command header; | |
3033 struct nk_vec2i a; | |
3034 struct nk_vec2i b; | |
3035 struct nk_vec2i c; | |
3036 struct nk_color color; | |
3037 }; | |
3038 | |
3039 struct nk_command_circle { | |
3040 struct nk_command header; | |
3041 short x, y; | |
3042 unsigned short line_thickness; | |
3043 unsigned short w, h; | |
3044 struct nk_color color; | |
3045 }; | |
3046 | |
3047 struct nk_command_circle_filled { | |
3048 struct nk_command header; | |
3049 short x, y; | |
3050 unsigned short w, h; | |
3051 struct nk_color color; | |
3052 }; | |
3053 | |
3054 struct nk_command_arc { | |
3055 struct nk_command header; | |
3056 short cx, cy; | |
3057 unsigned short r; | |
3058 unsigned short line_thickness; | |
3059 float a[2]; | |
3060 struct nk_color color; | |
3061 }; | |
3062 | |
3063 struct nk_command_arc_filled { | |
3064 struct nk_command header; | |
3065 short cx, cy; | |
3066 unsigned short r; | |
3067 float a[2]; | |
3068 struct nk_color color; | |
3069 }; | |
3070 | |
3071 struct nk_command_polygon { | |
3072 struct nk_command header; | |
3073 struct nk_color color; | |
3074 unsigned short line_thickness; | |
3075 unsigned short point_count; | |
3076 struct nk_vec2i points[1]; | |
3077 }; | |
3078 | |
3079 struct nk_command_polygon_filled { | |
3080 struct nk_command header; | |
3081 struct nk_color color; | |
3082 unsigned short point_count; | |
3083 struct nk_vec2i points[1]; | |
3084 }; | |
3085 | |
3086 struct nk_command_polyline { | |
3087 struct nk_command header; | |
3088 struct nk_color color; | |
3089 unsigned short line_thickness; | |
3090 unsigned short point_count; | |
3091 struct nk_vec2i points[1]; | |
3092 }; | |
3093 | |
3094 struct nk_command_image { | |
3095 struct nk_command header; | |
3096 short x, y; | |
3097 unsigned short w, h; | |
3098 struct nk_image img; | |
3099 struct nk_color col; | |
3100 }; | |
3101 | |
3102 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y, | |
3103 unsigned short w, unsigned short h, nk_handle callback_data); | |
3104 struct nk_command_custom { | |
3105 struct nk_command header; | |
3106 short x, y; | |
3107 unsigned short w, h; | |
3108 nk_handle callback_data; | |
3109 nk_command_custom_callback callback; | |
3110 }; | |
3111 | |
3112 struct nk_command_text { | |
3113 struct nk_command header; | |
3114 const struct nk_user_font *font; | |
3115 struct nk_color background; | |
3116 struct nk_color foreground; | |
3117 short x, y; | |
3118 unsigned short w, h; | |
3119 float height; | |
3120 int length; | |
3121 char string[1]; | |
3122 }; | |
3123 | |
3124 enum nk_command_clipping { | |
3125 NK_CLIPPING_OFF = nk_false, | |
3126 NK_CLIPPING_ON = nk_true | |
3127 }; | |
3128 | |
3129 struct nk_command_buffer { | |
3130 struct nk_buffer *base; | |
3131 struct nk_rect clip; | |
3132 int use_clipping; | |
3133 nk_handle userdata; | |
3134 nk_size begin, end, last; | |
3135 }; | |
3136 | |
3137 /* shape outlines */ | |
3138 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color); | |
3139 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); | |
3140 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); | |
3141 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); | |
3142 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color); | |
3143 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); | |
3144 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); | |
3145 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); | |
3146 | |
3147 /* filled shades */ | |
3148 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); | |
3149 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom); | |
3150 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); | |
3151 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color); | |
3152 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color); | |
3153 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); | |
3154 | |
3155 /* misc */ | |
3156 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); | |
3157 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color); | |
3158 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); | |
3159 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr); | |
3160 | |
3161 /* =============================================================== | |
3162 * | |
3163 * INPUT | |
3164 * | |
3165 * ===============================================================*/ | |
3166 struct nk_mouse_button { | |
3167 int down; | |
3168 unsigned int clicked; | |
3169 struct nk_vec2 clicked_pos; | |
3170 }; | |
3171 struct nk_mouse { | |
3172 struct nk_mouse_button buttons[NK_BUTTON_MAX]; | |
3173 struct nk_vec2 pos; | |
3174 struct nk_vec2 prev; | |
3175 struct nk_vec2 delta; | |
3176 struct nk_vec2 scroll_delta; | |
3177 unsigned char grab; | |
3178 unsigned char grabbed; | |
3179 unsigned char ungrab; | |
3180 }; | |
3181 | |
3182 struct nk_key { | |
3183 int down; | |
3184 unsigned int clicked; | |
3185 }; | |
3186 struct nk_keyboard { | |
3187 struct nk_key keys[NK_KEY_MAX]; | |
3188 char text[NK_INPUT_MAX]; | |
3189 int text_len; | |
3190 }; | |
3191 | |
3192 struct nk_input { | |
3193 struct nk_keyboard keyboard; | |
3194 struct nk_mouse mouse; | |
3195 }; | |
3196 | |
3197 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); | |
3198 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); | |
3199 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down); | |
3200 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); | |
3201 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down); | |
3202 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); | |
3203 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); | |
3204 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); | |
3205 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); | |
3206 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); | |
3207 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); | |
3208 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); | |
3209 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); | |
3210 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys); | |
3211 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); | |
3212 | |
3213 /* =============================================================== | |
3214 * | |
3215 * DRAW LIST | |
3216 * | |
3217 * ===============================================================*/ | |
3218 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
3219 /* The optional vertex buffer draw list provides a 2D drawing context | |
3220 with antialiasing functionality which takes basic filled or outlined shapes | |
3221 or a path and outputs vertexes, elements and draw commands. | |
3222 The actual draw list API is not required to be used directly while using this | |
3223 library since converting the default library draw command output is done by | |
3224 just calling `nk_convert` but I decided to still make this library accessible | |
3225 since it can be useful. | |
3226 | |
3227 The draw list is based on a path buffering and polygon and polyline | |
3228 rendering API which allows a lot of ways to draw 2D content to screen. | |
3229 In fact it is probably more powerful than needed but allows even more crazy | |
3230 things than this library provides by default. | |
3231 */ | |
3232 typedef nk_ushort nk_draw_index; | |
3233 enum nk_draw_list_stroke { | |
3234 NK_STROKE_OPEN = nk_false, | |
3235 /* build up path has no connection back to the beginning */ | |
3236 NK_STROKE_CLOSED = nk_true | |
3237 /* build up path has a connection back to the beginning */ | |
3238 }; | |
3239 | |
3240 enum nk_draw_vertex_layout_attribute { | |
3241 NK_VERTEX_POSITION, | |
3242 NK_VERTEX_COLOR, | |
3243 NK_VERTEX_TEXCOORD, | |
3244 NK_VERTEX_ATTRIBUTE_COUNT | |
3245 }; | |
3246 | |
3247 enum nk_draw_vertex_layout_format { | |
3248 NK_FORMAT_SCHAR, | |
3249 NK_FORMAT_SSHORT, | |
3250 NK_FORMAT_SINT, | |
3251 NK_FORMAT_UCHAR, | |
3252 NK_FORMAT_USHORT, | |
3253 NK_FORMAT_UINT, | |
3254 NK_FORMAT_FLOAT, | |
3255 NK_FORMAT_DOUBLE, | |
3256 | |
3257 NK_FORMAT_COLOR_BEGIN, | |
3258 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, | |
3259 NK_FORMAT_R16G15B16, | |
3260 NK_FORMAT_R32G32B32, | |
3261 | |
3262 NK_FORMAT_R8G8B8A8, | |
3263 NK_FORMAT_B8G8R8A8, | |
3264 NK_FORMAT_R16G15B16A16, | |
3265 NK_FORMAT_R32G32B32A32, | |
3266 NK_FORMAT_R32G32B32A32_FLOAT, | |
3267 NK_FORMAT_R32G32B32A32_DOUBLE, | |
3268 | |
3269 NK_FORMAT_RGB32, | |
3270 NK_FORMAT_RGBA32, | |
3271 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, | |
3272 NK_FORMAT_COUNT | |
3273 }; | |
3274 | |
3275 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 | |
3276 struct nk_draw_vertex_layout_element { | |
3277 enum nk_draw_vertex_layout_attribute attribute; | |
3278 enum nk_draw_vertex_layout_format format; | |
3279 nk_size offset; | |
3280 }; | |
3281 | |
3282 struct nk_draw_command { | |
3283 unsigned int elem_count; | |
3284 /* number of elements in the current draw batch */ | |
3285 struct nk_rect clip_rect; | |
3286 /* current screen clipping rectangle */ | |
3287 nk_handle texture; | |
3288 /* current texture to set */ | |
3289 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
3290 nk_handle userdata; | |
3291 #endif | |
3292 }; | |
3293 | |
3294 struct nk_draw_list { | |
3295 struct nk_rect clip_rect; | |
3296 struct nk_vec2 circle_vtx[12]; | |
3297 struct nk_convert_config config; | |
3298 | |
3299 struct nk_buffer *buffer; | |
3300 struct nk_buffer *vertices; | |
3301 struct nk_buffer *elements; | |
3302 | |
3303 unsigned int element_count; | |
3304 unsigned int vertex_count; | |
3305 unsigned int cmd_count; | |
3306 nk_size cmd_offset; | |
3307 | |
3308 unsigned int path_count; | |
3309 unsigned int path_offset; | |
3310 | |
3311 enum nk_anti_aliasing line_AA; | |
3312 enum nk_anti_aliasing shape_AA; | |
3313 | |
3314 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
3315 nk_handle userdata; | |
3316 #endif | |
3317 }; | |
3318 | |
3319 /* draw list */ | |
3320 NK_API void nk_draw_list_init(struct nk_draw_list*); | |
3321 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa); | |
3322 NK_API void nk_draw_list_clear(struct nk_draw_list*); | |
3323 | |
3324 /* drawing */ | |
3325 #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)) | |
3326 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); | |
3327 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*); | |
3328 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); | |
3329 NK_API void nk_draw_list_clear(struct nk_draw_list *list); | |
3330 | |
3331 /* path */ | |
3332 NK_API void nk_draw_list_path_clear(struct nk_draw_list*); | |
3333 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); | |
3334 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max); | |
3335 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments); | |
3336 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); | |
3337 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments); | |
3338 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); | |
3339 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); | |
3340 | |
3341 /* stroke */ | |
3342 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness); | |
3343 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); | |
3344 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness); | |
3345 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness); | |
3346 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness); | |
3347 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing); | |
3348 | |
3349 /* fill */ | |
3350 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); | |
3351 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom); | |
3352 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color); | |
3353 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs); | |
3354 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing); | |
3355 | |
3356 /* misc */ | |
3357 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); | |
3358 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color); | |
3359 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
3360 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); | |
3361 #endif | |
3362 | |
3363 #endif | |
3364 | |
3365 /* =============================================================== | |
3366 * | |
3367 * GUI | |
3368 * | |
3369 * ===============================================================*/ | |
3370 enum nk_style_item_type { | |
3371 NK_STYLE_ITEM_COLOR, | |
3372 NK_STYLE_ITEM_IMAGE | |
3373 }; | |
3374 | |
3375 union nk_style_item_data { | |
3376 struct nk_image image; | |
3377 struct nk_color color; | |
3378 }; | |
3379 | |
3380 struct nk_style_item { | |
3381 enum nk_style_item_type type; | |
3382 union nk_style_item_data data; | |
3383 }; | |
3384 | |
3385 struct nk_style_text { | |
3386 struct nk_color color; | |
3387 struct nk_vec2 padding; | |
3388 }; | |
3389 | |
3390 struct nk_style_button { | |
3391 /* background */ | |
3392 struct nk_style_item normal; | |
3393 struct nk_style_item hover; | |
3394 struct nk_style_item active; | |
3395 struct nk_color border_color; | |
3396 | |
3397 /* text */ | |
3398 struct nk_color text_background; | |
3399 struct nk_color text_normal; | |
3400 struct nk_color text_hover; | |
3401 struct nk_color text_active; | |
3402 nk_flags text_alignment; | |
3403 | |
3404 /* properties */ | |
3405 float border; | |
3406 float rounding; | |
3407 struct nk_vec2 padding; | |
3408 struct nk_vec2 image_padding; | |
3409 struct nk_vec2 touch_padding; | |
3410 | |
3411 /* optional user callbacks */ | |
3412 nk_handle userdata; | |
3413 void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); | |
3414 void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); | |
3415 }; | |
3416 | |
3417 struct nk_style_toggle { | |
3418 /* background */ | |
3419 struct nk_style_item normal; | |
3420 struct nk_style_item hover; | |
3421 struct nk_style_item active; | |
3422 struct nk_color border_color; | |
3423 | |
3424 /* cursor */ | |
3425 struct nk_style_item cursor_normal; | |
3426 struct nk_style_item cursor_hover; | |
3427 | |
3428 /* text */ | |
3429 struct nk_color text_normal; | |
3430 struct nk_color text_hover; | |
3431 struct nk_color text_active; | |
3432 struct nk_color text_background; | |
3433 nk_flags text_alignment; | |
3434 | |
3435 /* properties */ | |
3436 struct nk_vec2 padding; | |
3437 struct nk_vec2 touch_padding; | |
3438 float spacing; | |
3439 float border; | |
3440 | |
3441 /* optional user callbacks */ | |
3442 nk_handle userdata; | |
3443 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3444 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3445 }; | |
3446 | |
3447 struct nk_style_selectable { | |
3448 /* background (inactive) */ | |
3449 struct nk_style_item normal; | |
3450 struct nk_style_item hover; | |
3451 struct nk_style_item pressed; | |
3452 | |
3453 /* background (active) */ | |
3454 struct nk_style_item normal_active; | |
3455 struct nk_style_item hover_active; | |
3456 struct nk_style_item pressed_active; | |
3457 | |
3458 /* text color (inactive) */ | |
3459 struct nk_color text_normal; | |
3460 struct nk_color text_hover; | |
3461 struct nk_color text_pressed; | |
3462 | |
3463 /* text color (active) */ | |
3464 struct nk_color text_normal_active; | |
3465 struct nk_color text_hover_active; | |
3466 struct nk_color text_pressed_active; | |
3467 struct nk_color text_background; | |
3468 nk_flags text_alignment; | |
3469 | |
3470 /* properties */ | |
3471 float rounding; | |
3472 struct nk_vec2 padding; | |
3473 struct nk_vec2 touch_padding; | |
3474 struct nk_vec2 image_padding; | |
3475 | |
3476 /* optional user callbacks */ | |
3477 nk_handle userdata; | |
3478 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3479 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3480 }; | |
3481 | |
3482 struct nk_style_slider { | |
3483 /* background */ | |
3484 struct nk_style_item normal; | |
3485 struct nk_style_item hover; | |
3486 struct nk_style_item active; | |
3487 struct nk_color border_color; | |
3488 | |
3489 /* background bar */ | |
3490 struct nk_color bar_normal; | |
3491 struct nk_color bar_hover; | |
3492 struct nk_color bar_active; | |
3493 struct nk_color bar_filled; | |
3494 | |
3495 /* cursor */ | |
3496 struct nk_style_item cursor_normal; | |
3497 struct nk_style_item cursor_hover; | |
3498 struct nk_style_item cursor_active; | |
3499 | |
3500 /* properties */ | |
3501 float border; | |
3502 float rounding; | |
3503 float bar_height; | |
3504 struct nk_vec2 padding; | |
3505 struct nk_vec2 spacing; | |
3506 struct nk_vec2 cursor_size; | |
3507 | |
3508 /* optional buttons */ | |
3509 int show_buttons; | |
3510 struct nk_style_button inc_button; | |
3511 struct nk_style_button dec_button; | |
3512 enum nk_symbol_type inc_symbol; | |
3513 enum nk_symbol_type dec_symbol; | |
3514 | |
3515 /* optional user callbacks */ | |
3516 nk_handle userdata; | |
3517 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3518 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3519 }; | |
3520 | |
3521 struct nk_style_progress { | |
3522 /* background */ | |
3523 struct nk_style_item normal; | |
3524 struct nk_style_item hover; | |
3525 struct nk_style_item active; | |
3526 struct nk_color border_color; | |
3527 | |
3528 /* cursor */ | |
3529 struct nk_style_item cursor_normal; | |
3530 struct nk_style_item cursor_hover; | |
3531 struct nk_style_item cursor_active; | |
3532 struct nk_color cursor_border_color; | |
3533 | |
3534 /* properties */ | |
3535 float rounding; | |
3536 float border; | |
3537 float cursor_border; | |
3538 float cursor_rounding; | |
3539 struct nk_vec2 padding; | |
3540 | |
3541 /* optional user callbacks */ | |
3542 nk_handle userdata; | |
3543 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3544 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3545 }; | |
3546 | |
3547 struct nk_style_scrollbar { | |
3548 /* background */ | |
3549 struct nk_style_item normal; | |
3550 struct nk_style_item hover; | |
3551 struct nk_style_item active; | |
3552 struct nk_color border_color; | |
3553 | |
3554 /* cursor */ | |
3555 struct nk_style_item cursor_normal; | |
3556 struct nk_style_item cursor_hover; | |
3557 struct nk_style_item cursor_active; | |
3558 struct nk_color cursor_border_color; | |
3559 | |
3560 /* properties */ | |
3561 float border; | |
3562 float rounding; | |
3563 float border_cursor; | |
3564 float rounding_cursor; | |
3565 struct nk_vec2 padding; | |
3566 | |
3567 /* optional buttons */ | |
3568 int show_buttons; | |
3569 struct nk_style_button inc_button; | |
3570 struct nk_style_button dec_button; | |
3571 enum nk_symbol_type inc_symbol; | |
3572 enum nk_symbol_type dec_symbol; | |
3573 | |
3574 /* optional user callbacks */ | |
3575 nk_handle userdata; | |
3576 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3577 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3578 }; | |
3579 | |
3580 struct nk_style_edit { | |
3581 /* background */ | |
3582 struct nk_style_item normal; | |
3583 struct nk_style_item hover; | |
3584 struct nk_style_item active; | |
3585 struct nk_color border_color; | |
3586 struct nk_style_scrollbar scrollbar; | |
3587 | |
3588 /* cursor */ | |
3589 struct nk_color cursor_normal; | |
3590 struct nk_color cursor_hover; | |
3591 struct nk_color cursor_text_normal; | |
3592 struct nk_color cursor_text_hover; | |
3593 | |
3594 /* text (unselected) */ | |
3595 struct nk_color text_normal; | |
3596 struct nk_color text_hover; | |
3597 struct nk_color text_active; | |
3598 | |
3599 /* text (selected) */ | |
3600 struct nk_color selected_normal; | |
3601 struct nk_color selected_hover; | |
3602 struct nk_color selected_text_normal; | |
3603 struct nk_color selected_text_hover; | |
3604 | |
3605 /* properties */ | |
3606 float border; | |
3607 float rounding; | |
3608 float cursor_size; | |
3609 struct nk_vec2 scrollbar_size; | |
3610 struct nk_vec2 padding; | |
3611 float row_padding; | |
3612 }; | |
3613 | |
3614 struct nk_style_property { | |
3615 /* background */ | |
3616 struct nk_style_item normal; | |
3617 struct nk_style_item hover; | |
3618 struct nk_style_item active; | |
3619 struct nk_color border_color; | |
3620 | |
3621 /* text */ | |
3622 struct nk_color label_normal; | |
3623 struct nk_color label_hover; | |
3624 struct nk_color label_active; | |
3625 | |
3626 /* symbols */ | |
3627 enum nk_symbol_type sym_left; | |
3628 enum nk_symbol_type sym_right; | |
3629 | |
3630 /* properties */ | |
3631 float border; | |
3632 float rounding; | |
3633 struct nk_vec2 padding; | |
3634 | |
3635 struct nk_style_edit edit; | |
3636 struct nk_style_button inc_button; | |
3637 struct nk_style_button dec_button; | |
3638 | |
3639 /* optional user callbacks */ | |
3640 nk_handle userdata; | |
3641 void(*draw_begin)(struct nk_command_buffer*, nk_handle); | |
3642 void(*draw_end)(struct nk_command_buffer*, nk_handle); | |
3643 }; | |
3644 | |
3645 struct nk_style_chart { | |
3646 /* colors */ | |
3647 struct nk_style_item background; | |
3648 struct nk_color border_color; | |
3649 struct nk_color selected_color; | |
3650 struct nk_color color; | |
3651 | |
3652 /* properties */ | |
3653 float border; | |
3654 float rounding; | |
3655 struct nk_vec2 padding; | |
3656 }; | |
3657 | |
3658 struct nk_style_combo { | |
3659 /* background */ | |
3660 struct nk_style_item normal; | |
3661 struct nk_style_item hover; | |
3662 struct nk_style_item active; | |
3663 struct nk_color border_color; | |
3664 | |
3665 /* label */ | |
3666 struct nk_color label_normal; | |
3667 struct nk_color label_hover; | |
3668 struct nk_color label_active; | |
3669 | |
3670 /* symbol */ | |
3671 struct nk_color symbol_normal; | |
3672 struct nk_color symbol_hover; | |
3673 struct nk_color symbol_active; | |
3674 | |
3675 /* button */ | |
3676 struct nk_style_button button; | |
3677 enum nk_symbol_type sym_normal; | |
3678 enum nk_symbol_type sym_hover; | |
3679 enum nk_symbol_type sym_active; | |
3680 | |
3681 /* properties */ | |
3682 float border; | |
3683 float rounding; | |
3684 struct nk_vec2 content_padding; | |
3685 struct nk_vec2 button_padding; | |
3686 struct nk_vec2 spacing; | |
3687 }; | |
3688 | |
3689 struct nk_style_tab { | |
3690 /* background */ | |
3691 struct nk_style_item background; | |
3692 struct nk_color border_color; | |
3693 struct nk_color text; | |
3694 | |
3695 /* button */ | |
3696 struct nk_style_button tab_maximize_button; | |
3697 struct nk_style_button tab_minimize_button; | |
3698 struct nk_style_button node_maximize_button; | |
3699 struct nk_style_button node_minimize_button; | |
3700 enum nk_symbol_type sym_minimize; | |
3701 enum nk_symbol_type sym_maximize; | |
3702 | |
3703 /* properties */ | |
3704 float border; | |
3705 float rounding; | |
3706 float indent; | |
3707 struct nk_vec2 padding; | |
3708 struct nk_vec2 spacing; | |
3709 }; | |
3710 | |
3711 enum nk_style_header_align { | |
3712 NK_HEADER_LEFT, | |
3713 NK_HEADER_RIGHT | |
3714 }; | |
3715 struct nk_style_window_header { | |
3716 /* background */ | |
3717 struct nk_style_item normal; | |
3718 struct nk_style_item hover; | |
3719 struct nk_style_item active; | |
3720 | |
3721 /* button */ | |
3722 struct nk_style_button close_button; | |
3723 struct nk_style_button minimize_button; | |
3724 enum nk_symbol_type close_symbol; | |
3725 enum nk_symbol_type minimize_symbol; | |
3726 enum nk_symbol_type maximize_symbol; | |
3727 | |
3728 /* title */ | |
3729 struct nk_color label_normal; | |
3730 struct nk_color label_hover; | |
3731 struct nk_color label_active; | |
3732 | |
3733 /* properties */ | |
3734 enum nk_style_header_align align; | |
3735 struct nk_vec2 padding; | |
3736 struct nk_vec2 label_padding; | |
3737 struct nk_vec2 spacing; | |
3738 }; | |
3739 | |
3740 struct nk_style_window { | |
3741 struct nk_style_window_header header; | |
3742 struct nk_style_item fixed_background; | |
3743 struct nk_color background; | |
3744 | |
3745 struct nk_color border_color; | |
3746 struct nk_color popup_border_color; | |
3747 struct nk_color combo_border_color; | |
3748 struct nk_color contextual_border_color; | |
3749 struct nk_color menu_border_color; | |
3750 struct nk_color group_border_color; | |
3751 struct nk_color tooltip_border_color; | |
3752 struct nk_style_item scaler; | |
3753 | |
3754 float border; | |
3755 float combo_border; | |
3756 float contextual_border; | |
3757 float menu_border; | |
3758 float group_border; | |
3759 float tooltip_border; | |
3760 float popup_border; | |
3761 float min_row_height_padding; | |
3762 | |
3763 float rounding; | |
3764 struct nk_vec2 spacing; | |
3765 struct nk_vec2 scrollbar_size; | |
3766 struct nk_vec2 min_size; | |
3767 | |
3768 struct nk_vec2 padding; | |
3769 struct nk_vec2 group_padding; | |
3770 struct nk_vec2 popup_padding; | |
3771 struct nk_vec2 combo_padding; | |
3772 struct nk_vec2 contextual_padding; | |
3773 struct nk_vec2 menu_padding; | |
3774 struct nk_vec2 tooltip_padding; | |
3775 }; | |
3776 | |
3777 struct nk_style { | |
3778 const struct nk_user_font *font; | |
3779 const struct nk_cursor *cursors[NK_CURSOR_COUNT]; | |
3780 const struct nk_cursor *cursor_active; | |
3781 struct nk_cursor *cursor_last; | |
3782 int cursor_visible; | |
3783 | |
3784 struct nk_style_text text; | |
3785 struct nk_style_button button; | |
3786 struct nk_style_button contextual_button; | |
3787 struct nk_style_button menu_button; | |
3788 struct nk_style_toggle option; | |
3789 struct nk_style_toggle checkbox; | |
3790 struct nk_style_selectable selectable; | |
3791 struct nk_style_slider slider; | |
3792 struct nk_style_progress progress; | |
3793 struct nk_style_property property; | |
3794 struct nk_style_edit edit; | |
3795 struct nk_style_chart chart; | |
3796 struct nk_style_scrollbar scrollh; | |
3797 struct nk_style_scrollbar scrollv; | |
3798 struct nk_style_tab tab; | |
3799 struct nk_style_combo combo; | |
3800 struct nk_style_window window; | |
3801 }; | |
3802 | |
3803 NK_API struct nk_style_item nk_style_item_image(struct nk_image img); | |
3804 NK_API struct nk_style_item nk_style_item_color(struct nk_color); | |
3805 NK_API struct nk_style_item nk_style_item_hide(void); | |
3806 | |
3807 /*============================================================== | |
3808 * PANEL | |
3809 * =============================================================*/ | |
3810 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS | |
3811 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16 | |
3812 #endif | |
3813 #ifndef NK_CHART_MAX_SLOT | |
3814 #define NK_CHART_MAX_SLOT 4 | |
3815 #endif | |
3816 | |
3817 enum nk_panel_type { | |
3818 NK_PANEL_WINDOW = NK_FLAG(0), | |
3819 NK_PANEL_GROUP = NK_FLAG(1), | |
3820 NK_PANEL_POPUP = NK_FLAG(2), | |
3821 NK_PANEL_CONTEXTUAL = NK_FLAG(4), | |
3822 NK_PANEL_COMBO = NK_FLAG(5), | |
3823 NK_PANEL_MENU = NK_FLAG(6), | |
3824 NK_PANEL_TOOLTIP = NK_FLAG(7) | |
3825 }; | |
3826 enum nk_panel_set { | |
3827 NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, | |
3828 NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, | |
3829 NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP | |
3830 }; | |
3831 | |
3832 struct nk_chart_slot { | |
3833 enum nk_chart_type type; | |
3834 struct nk_color color; | |
3835 struct nk_color highlight; | |
3836 float min, max, range; | |
3837 int count; | |
3838 struct nk_vec2 last; | |
3839 int index; | |
3840 }; | |
3841 | |
3842 struct nk_chart { | |
3843 int slot; | |
3844 float x, y, w, h; | |
3845 struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; | |
3846 }; | |
3847 | |
3848 enum nk_panel_row_layout_type { | |
3849 NK_LAYOUT_DYNAMIC_FIXED = 0, | |
3850 NK_LAYOUT_DYNAMIC_ROW, | |
3851 NK_LAYOUT_DYNAMIC_FREE, | |
3852 NK_LAYOUT_DYNAMIC, | |
3853 NK_LAYOUT_STATIC_FIXED, | |
3854 NK_LAYOUT_STATIC_ROW, | |
3855 NK_LAYOUT_STATIC_FREE, | |
3856 NK_LAYOUT_STATIC, | |
3857 NK_LAYOUT_TEMPLATE, | |
3858 NK_LAYOUT_COUNT | |
3859 }; | |
3860 struct nk_row_layout { | |
3861 enum nk_panel_row_layout_type type; | |
3862 int index; | |
3863 float height; | |
3864 float min_height; | |
3865 int columns; | |
3866 const float *ratio; | |
3867 float item_width; | |
3868 float item_height; | |
3869 float item_offset; | |
3870 float filled; | |
3871 struct nk_rect item; | |
3872 int tree_depth; | |
3873 float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]; | |
3874 }; | |
3875 | |
3876 struct nk_popup_buffer { | |
3877 nk_size begin; | |
3878 nk_size parent; | |
3879 nk_size last; | |
3880 nk_size end; | |
3881 int active; | |
3882 }; | |
3883 | |
3884 struct nk_menu_state { | |
3885 float x, y, w, h; | |
3886 struct nk_scroll offset; | |
3887 }; | |
3888 | |
3889 struct nk_panel { | |
3890 enum nk_panel_type type; | |
3891 nk_flags flags; | |
3892 struct nk_rect bounds; | |
3893 nk_uint *offset_x; | |
3894 nk_uint *offset_y; | |
3895 float at_x, at_y, max_x; | |
3896 float footer_height; | |
3897 float header_height; | |
3898 float border; | |
3899 unsigned int has_scrolling; | |
3900 struct nk_rect clip; | |
3901 struct nk_menu_state menu; | |
3902 struct nk_row_layout row; | |
3903 struct nk_chart chart; | |
3904 struct nk_command_buffer *buffer; | |
3905 struct nk_panel *parent; | |
3906 }; | |
3907 | |
3908 /*============================================================== | |
3909 * WINDOW | |
3910 * =============================================================*/ | |
3911 #ifndef NK_WINDOW_MAX_NAME | |
3912 #define NK_WINDOW_MAX_NAME 64 | |
3913 #endif | |
3914 | |
3915 struct nk_table; | |
3916 enum nk_window_flags { | |
3917 NK_WINDOW_PRIVATE = NK_FLAG(11), | |
3918 NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, | |
3919 /* special window type growing up in height while being filled to a certain maximum height */ | |
3920 NK_WINDOW_ROM = NK_FLAG(12), | |
3921 /* sets window widgets into a read only mode and does not allow input changes */ | |
3922 NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT, | |
3923 /* prevents all interaction caused by input to either window or widgets inside */ | |
3924 NK_WINDOW_HIDDEN = NK_FLAG(13), | |
3925 /* Hides window and stops any window interaction and drawing */ | |
3926 NK_WINDOW_CLOSED = NK_FLAG(14), | |
3927 /* Directly closes and frees the window at the end of the frame */ | |
3928 NK_WINDOW_MINIMIZED = NK_FLAG(15), | |
3929 /* marks the window as minimized */ | |
3930 NK_WINDOW_REMOVE_ROM = NK_FLAG(16) | |
3931 /* Removes read only mode at the end of the window */ | |
3932 }; | |
3933 | |
3934 struct nk_popup_state { | |
3935 struct nk_window *win; | |
3936 enum nk_panel_type type; | |
3937 struct nk_popup_buffer buf; | |
3938 nk_hash name; | |
3939 int active; | |
3940 unsigned combo_count; | |
3941 unsigned con_count, con_old; | |
3942 unsigned active_con; | |
3943 struct nk_rect header; | |
3944 }; | |
3945 | |
3946 struct nk_edit_state { | |
3947 nk_hash name; | |
3948 unsigned int seq; | |
3949 unsigned int old; | |
3950 int active, prev; | |
3951 int cursor; | |
3952 int sel_start; | |
3953 int sel_end; | |
3954 struct nk_scroll scrollbar; | |
3955 unsigned char mode; | |
3956 unsigned char single_line; | |
3957 }; | |
3958 | |
3959 struct nk_property_state { | |
3960 int active, prev; | |
3961 char buffer[NK_MAX_NUMBER_BUFFER]; | |
3962 int length; | |
3963 int cursor; | |
3964 int select_start; | |
3965 int select_end; | |
3966 nk_hash name; | |
3967 unsigned int seq; | |
3968 unsigned int old; | |
3969 int state; | |
3970 }; | |
3971 | |
3972 struct nk_window { | |
3973 unsigned int seq; | |
3974 nk_hash name; | |
3975 char name_string[NK_WINDOW_MAX_NAME]; | |
3976 nk_flags flags; | |
3977 | |
3978 struct nk_rect bounds; | |
3979 struct nk_scroll scrollbar; | |
3980 struct nk_command_buffer buffer; | |
3981 struct nk_panel *layout; | |
3982 float scrollbar_hiding_timer; | |
3983 | |
3984 /* persistent widget state */ | |
3985 struct nk_property_state property; | |
3986 struct nk_popup_state popup; | |
3987 struct nk_edit_state edit; | |
3988 unsigned int scrolled; | |
3989 | |
3990 struct nk_table *tables; | |
3991 unsigned int table_count; | |
3992 | |
3993 /* window list hooks */ | |
3994 struct nk_window *next; | |
3995 struct nk_window *prev; | |
3996 struct nk_window *parent; | |
3997 }; | |
3998 | |
3999 /*============================================================== | |
4000 * STACK | |
4001 * =============================================================*/ | |
4002 /* The style modifier stack can be used to temporarily change a | |
4003 * property inside `nk_style`. For example if you want a special | |
4004 * red button you can temporarily push the old button color onto a stack | |
4005 * draw the button with a red color and then you just pop the old color | |
4006 * back from the stack: | |
4007 * | |
4008 * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); | |
4009 * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); | |
4010 * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); | |
4011 * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); | |
4012 * | |
4013 * nk_button(...); | |
4014 * | |
4015 * nk_style_pop_style_item(ctx); | |
4016 * nk_style_pop_style_item(ctx); | |
4017 * nk_style_pop_style_item(ctx); | |
4018 * nk_style_pop_vec2(ctx); | |
4019 * | |
4020 * Nuklear has a stack for style_items, float properties, vector properties, | |
4021 * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack | |
4022 * which can be changed at compile time. | |
4023 */ | |
4024 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE | |
4025 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 | |
4026 #endif | |
4027 | |
4028 #ifndef NK_FONT_STACK_SIZE | |
4029 #define NK_FONT_STACK_SIZE 8 | |
4030 #endif | |
4031 | |
4032 #ifndef NK_STYLE_ITEM_STACK_SIZE | |
4033 #define NK_STYLE_ITEM_STACK_SIZE 16 | |
4034 #endif | |
4035 | |
4036 #ifndef NK_FLOAT_STACK_SIZE | |
4037 #define NK_FLOAT_STACK_SIZE 32 | |
4038 #endif | |
4039 | |
4040 #ifndef NK_VECTOR_STACK_SIZE | |
4041 #define NK_VECTOR_STACK_SIZE 16 | |
4042 #endif | |
4043 | |
4044 #ifndef NK_FLAGS_STACK_SIZE | |
4045 #define NK_FLAGS_STACK_SIZE 32 | |
4046 #endif | |
4047 | |
4048 #ifndef NK_COLOR_STACK_SIZE | |
4049 #define NK_COLOR_STACK_SIZE 32 | |
4050 #endif | |
4051 | |
4052 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ | |
4053 struct nk_config_stack_##name##_element {\ | |
4054 prefix##_##type *address;\ | |
4055 prefix##_##type old_value;\ | |
4056 } | |
4057 #define NK_CONFIG_STACK(type,size)\ | |
4058 struct nk_config_stack_##type {\ | |
4059 int head;\ | |
4060 struct nk_config_stack_##type##_element elements[size];\ | |
4061 } | |
4062 | |
4063 #define nk_float float | |
4064 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); | |
4065 NK_CONFIGURATION_STACK_TYPE(nk ,float, float); | |
4066 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); | |
4067 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); | |
4068 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); | |
4069 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); | |
4070 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); | |
4071 | |
4072 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); | |
4073 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); | |
4074 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); | |
4075 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); | |
4076 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); | |
4077 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); | |
4078 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); | |
4079 | |
4080 struct nk_configuration_stacks { | |
4081 struct nk_config_stack_style_item style_items; | |
4082 struct nk_config_stack_float floats; | |
4083 struct nk_config_stack_vec2 vectors; | |
4084 struct nk_config_stack_flags flags; | |
4085 struct nk_config_stack_color colors; | |
4086 struct nk_config_stack_user_font fonts; | |
4087 struct nk_config_stack_button_behavior button_behaviors; | |
4088 }; | |
4089 | |
4090 /*============================================================== | |
4091 * CONTEXT | |
4092 * =============================================================*/ | |
4093 #define NK_VALUE_PAGE_CAPACITY \ | |
4094 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2) | |
4095 | |
4096 struct nk_table { | |
4097 unsigned int seq; | |
4098 unsigned int size; | |
4099 nk_hash keys[NK_VALUE_PAGE_CAPACITY]; | |
4100 nk_uint values[NK_VALUE_PAGE_CAPACITY]; | |
4101 struct nk_table *next, *prev; | |
4102 }; | |
4103 | |
4104 union nk_page_data { | |
4105 struct nk_table tbl; | |
4106 struct nk_panel pan; | |
4107 struct nk_window win; | |
4108 }; | |
4109 | |
4110 struct nk_page_element { | |
4111 union nk_page_data data; | |
4112 struct nk_page_element *next; | |
4113 struct nk_page_element *prev; | |
4114 }; | |
4115 | |
4116 struct nk_page { | |
4117 unsigned int size; | |
4118 struct nk_page *next; | |
4119 struct nk_page_element win[1]; | |
4120 }; | |
4121 | |
4122 struct nk_pool { | |
4123 struct nk_allocator alloc; | |
4124 enum nk_allocation_type type; | |
4125 unsigned int page_count; | |
4126 struct nk_page *pages; | |
4127 struct nk_page_element *freelist; | |
4128 unsigned capacity; | |
4129 nk_size size; | |
4130 nk_size cap; | |
4131 }; | |
4132 | |
4133 struct nk_context { | |
4134 /* public: can be accessed freely */ | |
4135 struct nk_input input; | |
4136 struct nk_style style; | |
4137 struct nk_buffer memory; | |
4138 struct nk_clipboard clip; | |
4139 nk_flags last_widget_state; | |
4140 enum nk_button_behavior button_behavior; | |
4141 struct nk_configuration_stacks stacks; | |
4142 float delta_time_seconds; | |
4143 | |
4144 /* private: | |
4145 should only be accessed if you | |
4146 know what you are doing */ | |
4147 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
4148 struct nk_draw_list draw_list; | |
4149 #endif | |
4150 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
4151 nk_handle userdata; | |
4152 #endif | |
4153 /* text editor objects are quite big because of an internal | |
4154 * undo/redo stack. Therefore it does not make sense to have one for | |
4155 * each window for temporary use cases, so I only provide *one* instance | |
4156 * for all windows. This works because the content is cleared anyway */ | |
4157 struct nk_text_edit text_edit; | |
4158 /* draw buffer used for overlay drawing operation like cursor */ | |
4159 struct nk_command_buffer overlay; | |
4160 | |
4161 /* windows */ | |
4162 int build; | |
4163 int use_pool; | |
4164 struct nk_pool pool; | |
4165 struct nk_window *begin; | |
4166 struct nk_window *end; | |
4167 struct nk_window *active; | |
4168 struct nk_window *current; | |
4169 struct nk_page_element *freelist; | |
4170 unsigned int count; | |
4171 unsigned int seq; | |
4172 }; | |
4173 | |
4174 /* ============================================================== | |
4175 * MATH | |
4176 * =============================================================== */ | |
4177 #define NK_PI 3.141592654f | |
4178 #define NK_UTF_INVALID 0xFFFD | |
4179 #define NK_MAX_FLOAT_PRECISION 2 | |
4180 | |
4181 #define NK_UNUSED(x) ((void)(x)) | |
4182 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) | |
4183 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) | |
4184 #define NK_ABS(a) (((a) < 0) ? -(a) : (a)) | |
4185 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b)) | |
4186 #define NK_INBOX(px, py, x, y, w, h)\ | |
4187 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) | |
4188 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ | |
4189 (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0))) | |
4190 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ | |
4191 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) | |
4192 | |
4193 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) | |
4194 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) | |
4195 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) | |
4196 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) | |
4197 | |
4198 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) | |
4199 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) | |
4200 #define nk_zero_struct(s) nk_zero(&s, sizeof(s)) | |
4201 | |
4202 /* ============================================================== | |
4203 * ALIGNMENT | |
4204 * =============================================================== */ | |
4205 /* Pointer to Integer type conversion for pointer alignment */ | |
4206 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ | |
4207 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) | |
4208 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) | |
4209 #elif !defined(__GNUC__) /* works for compilers other than LLVM */ | |
4210 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) | |
4211 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) | |
4212 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */ | |
4213 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) | |
4214 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) | |
4215 #else /* generates warning but works */ | |
4216 # define NK_UINT_TO_PTR(x) ((void*)(x)) | |
4217 # define NK_PTR_TO_UINT(x) ((nk_size)(x)) | |
4218 #endif | |
4219 | |
4220 #define NK_ALIGN_PTR(x, mask)\ | |
4221 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) | |
4222 #define NK_ALIGN_PTR_BACK(x, mask)\ | |
4223 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) | |
4224 | |
4225 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) | |
4226 #define NK_CONTAINER_OF(ptr,type,member)\ | |
4227 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) | |
4228 | |
4229 #ifdef __cplusplus | |
4230 } | |
4231 #endif | |
4232 | |
4233 #ifdef __cplusplus | |
4234 template<typename T> struct nk_alignof; | |
4235 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};}; | |
4236 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};}; | |
4237 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum { | |
4238 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};}; | |
4239 #define NK_ALIGNOF(t) (nk_alignof<t>::value) | |
4240 #elif defined(_MSC_VER) | |
4241 #define NK_ALIGNOF(t) (__alignof(t)) | |
4242 #else | |
4243 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) | |
4244 #endif | |
4245 | |
4246 #endif /* NK_NUKLEAR_H_ */ | |
4247 /* | |
4248 * ============================================================== | |
4249 * | |
4250 * IMPLEMENTATION | |
4251 * | |
4252 * =============================================================== | |
4253 */ | |
4254 #ifdef NK_IMPLEMENTATION | |
4255 | |
4256 #ifndef NK_POOL_DEFAULT_CAPACITY | |
4257 #define NK_POOL_DEFAULT_CAPACITY 16 | |
4258 #endif | |
4259 | |
4260 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE | |
4261 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) | |
4262 #endif | |
4263 | |
4264 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE | |
4265 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) | |
4266 #endif | |
4267 | |
4268 /* standard library headers */ | |
4269 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
4270 #include <stdlib.h> /* malloc, free */ | |
4271 #endif | |
4272 #ifdef NK_INCLUDE_STANDARD_IO | |
4273 #include <stdio.h> /* fopen, fclose,... */ | |
4274 #endif | |
4275 #ifdef NK_INCLUDE_STANDARD_VARARGS | |
4276 #include <stdarg.h> /* valist, va_start, va_end, ... */ | |
4277 #endif | |
4278 #ifndef NK_ASSERT | |
4279 #include <assert.h> | |
4280 #define NK_ASSERT(expr) assert(expr) | |
4281 #endif | |
4282 | |
4283 #ifndef NK_MEMSET | |
4284 #define NK_MEMSET nk_memset | |
4285 #endif | |
4286 #ifndef NK_MEMCPY | |
4287 #define NK_MEMCPY nk_memcopy | |
4288 #endif | |
4289 #ifndef NK_SQRT | |
4290 #define NK_SQRT nk_sqrt | |
4291 #endif | |
4292 #ifndef NK_SIN | |
4293 #define NK_SIN nk_sin | |
4294 #endif | |
4295 #ifndef NK_COS | |
4296 #define NK_COS nk_cos | |
4297 #endif | |
4298 #ifndef NK_STRTOD | |
4299 #define NK_STRTOD nk_strtod | |
4300 #endif | |
4301 #ifndef NK_DTOA | |
4302 #define NK_DTOA nk_dtoa | |
4303 #endif | |
4304 | |
4305 #define NK_DEFAULT (-1) | |
4306 | |
4307 #ifndef NK_VSNPRINTF | |
4308 /* If your compiler does support `vsnprintf` I would highly recommend | |
4309 * defining this to vsnprintf instead since `vsprintf` is basically | |
4310 * unbelievable unsafe and should *NEVER* be used. But I have to support | |
4311 * it since C89 only provides this unsafe version. */ | |
4312 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ | |
4313 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ | |
4314 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ | |
4315 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ | |
4316 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) | |
4317 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) | |
4318 #else | |
4319 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) | |
4320 #endif | |
4321 #endif | |
4322 | |
4323 #define NK_SCHAR_MIN (-127) | |
4324 #define NK_SCHAR_MAX 127 | |
4325 #define NK_UCHAR_MIN 0 | |
4326 #define NK_UCHAR_MAX 256 | |
4327 #define NK_SSHORT_MIN (-32767) | |
4328 #define NK_SSHORT_MAX 32767 | |
4329 #define NK_USHORT_MIN 0 | |
4330 #define NK_USHORT_MAX 65535 | |
4331 #define NK_SINT_MIN (-2147483647) | |
4332 #define NK_SINT_MAX 2147483647 | |
4333 #define NK_UINT_MIN 0 | |
4334 #define NK_UINT_MAX 4294967295u | |
4335 | |
4336 /* Make sure correct type size: | |
4337 * This will fire with a negative subscript error if the type sizes | |
4338 * are set incorrectly by the compiler, and compile out if not */ | |
4339 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); | |
4340 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); | |
4341 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); | |
4342 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); | |
4343 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); | |
4344 NK_STATIC_ASSERT(sizeof(nk_short) == 2); | |
4345 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); | |
4346 NK_STATIC_ASSERT(sizeof(nk_int) == 4); | |
4347 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); | |
4348 | |
4349 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; | |
4350 #define NK_FLOAT_PRECISION 0.00000000000001 | |
4351 | |
4352 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; | |
4353 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; | |
4354 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; | |
4355 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; | |
4356 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; | |
4357 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; | |
4358 | |
4359 /* | |
4360 * ============================================================== | |
4361 * | |
4362 * MATH | |
4363 * | |
4364 * =============================================================== | |
4365 */ | |
4366 /* Since nuklear is supposed to work on all systems providing floating point | |
4367 math without any dependencies I also had to implement my own math functions | |
4368 for sqrt, sin and cos. Since the actual highly accurate implementations for | |
4369 the standard library functions are quite complex and I do not need high | |
4370 precision for my use cases I use approximations. | |
4371 | |
4372 Sqrt | |
4373 ---- | |
4374 For square root nuklear uses the famous fast inverse square root: | |
4375 https://en.wikipedia.org/wiki/Fast_inverse_square_root with | |
4376 slightly tweaked magic constant. While on today's hardware it is | |
4377 probably not faster it is still fast and accurate enough for | |
4378 nuklear's use cases. IMPORTANT: this requires float format IEEE 754 | |
4379 | |
4380 Sine/Cosine | |
4381 ----------- | |
4382 All constants inside both function are generated Remez's minimax | |
4383 approximations for value range 0...2*PI. The reason why I decided to | |
4384 approximate exactly that range is that nuklear only needs sine and | |
4385 cosine to generate circles which only requires that exact range. | |
4386 In addition I used Remez instead of Taylor for additional precision: | |
4387 www.lolengine.net/blog/2011/12/21/better-function-approximations. | |
4388 | |
4389 The tool I used to generate constants for both sine and cosine | |
4390 (it can actually approximate a lot more functions) can be | |
4391 found here: www.lolengine.net/wiki/oss/lolremez | |
4392 */ | |
4393 NK_INTERN float | |
4394 nk_inv_sqrt(float number) | |
4395 { | |
4396 float x2; | |
4397 const float threehalfs = 1.5f; | |
4398 union {nk_uint i; float f;} conv = {0}; | |
4399 conv.f = number; | |
4400 x2 = number * 0.5f; | |
4401 conv.i = 0x5f375A84 - (conv.i >> 1); | |
4402 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); | |
4403 return conv.f; | |
4404 } | |
4405 | |
4406 NK_INTERN float | |
4407 nk_sqrt(float x) | |
4408 { | |
4409 return x * nk_inv_sqrt(x); | |
4410 } | |
4411 | |
4412 NK_INTERN float | |
4413 nk_sin(float x) | |
4414 { | |
4415 NK_STORAGE const float a0 = +1.91059300966915117e-31f; | |
4416 NK_STORAGE const float a1 = +1.00086760103908896f; | |
4417 NK_STORAGE const float a2 = -1.21276126894734565e-2f; | |
4418 NK_STORAGE const float a3 = -1.38078780785773762e-1f; | |
4419 NK_STORAGE const float a4 = -2.67353392911981221e-2f; | |
4420 NK_STORAGE const float a5 = +2.08026600266304389e-2f; | |
4421 NK_STORAGE const float a6 = -3.03996055049204407e-3f; | |
4422 NK_STORAGE const float a7 = +1.38235642404333740e-4f; | |
4423 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); | |
4424 } | |
4425 | |
4426 NK_INTERN float | |
4427 nk_cos(float x) | |
4428 { | |
4429 NK_STORAGE const float a0 = +1.00238601909309722f; | |
4430 NK_STORAGE const float a1 = -3.81919947353040024e-2f; | |
4431 NK_STORAGE const float a2 = -3.94382342128062756e-1f; | |
4432 NK_STORAGE const float a3 = -1.18134036025221444e-1f; | |
4433 NK_STORAGE const float a4 = +1.07123798512170878e-1f; | |
4434 NK_STORAGE const float a5 = -1.86637164165180873e-2f; | |
4435 NK_STORAGE const float a6 = +9.90140908664079833e-4f; | |
4436 NK_STORAGE const float a7 = -5.23022132118824778e-14f; | |
4437 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); | |
4438 } | |
4439 | |
4440 NK_INTERN nk_uint | |
4441 nk_round_up_pow2(nk_uint v) | |
4442 { | |
4443 v--; | |
4444 v |= v >> 1; | |
4445 v |= v >> 2; | |
4446 v |= v >> 4; | |
4447 v |= v >> 8; | |
4448 v |= v >> 16; | |
4449 v++; | |
4450 return v; | |
4451 } | |
4452 | |
4453 NK_API struct nk_rect | |
4454 nk_get_null_rect(void) | |
4455 { | |
4456 return nk_null_rect; | |
4457 } | |
4458 | |
4459 NK_API struct nk_rect | |
4460 nk_rect(float x, float y, float w, float h) | |
4461 { | |
4462 struct nk_rect r; | |
4463 r.x = x; r.y = y; | |
4464 r.w = w; r.h = h; | |
4465 return r; | |
4466 } | |
4467 | |
4468 NK_API struct nk_rect | |
4469 nk_recti(int x, int y, int w, int h) | |
4470 { | |
4471 struct nk_rect r; | |
4472 r.x = (float)x; | |
4473 r.y = (float)y; | |
4474 r.w = (float)w; | |
4475 r.h = (float)h; | |
4476 return r; | |
4477 } | |
4478 | |
4479 NK_API struct nk_rect | |
4480 nk_recta(struct nk_vec2 pos, struct nk_vec2 size) | |
4481 { | |
4482 return nk_rect(pos.x, pos.y, size.x, size.y); | |
4483 } | |
4484 | |
4485 NK_API struct nk_rect | |
4486 nk_rectv(const float *r) | |
4487 { | |
4488 return nk_rect(r[0], r[1], r[2], r[3]); | |
4489 } | |
4490 | |
4491 NK_API struct nk_rect | |
4492 nk_rectiv(const int *r) | |
4493 { | |
4494 return nk_recti(r[0], r[1], r[2], r[3]); | |
4495 } | |
4496 | |
4497 NK_API struct nk_vec2 | |
4498 nk_rect_pos(struct nk_rect r) | |
4499 { | |
4500 struct nk_vec2 ret; | |
4501 ret.x = r.x; ret.y = r.y; | |
4502 return ret; | |
4503 } | |
4504 | |
4505 NK_API struct nk_vec2 | |
4506 nk_rect_size(struct nk_rect r) | |
4507 { | |
4508 struct nk_vec2 ret; | |
4509 ret.x = r.w; ret.y = r.h; | |
4510 return ret; | |
4511 } | |
4512 | |
4513 NK_INTERN struct nk_rect | |
4514 nk_shrink_rect(struct nk_rect r, float amount) | |
4515 { | |
4516 struct nk_rect res; | |
4517 r.w = NK_MAX(r.w, 2 * amount); | |
4518 r.h = NK_MAX(r.h, 2 * amount); | |
4519 res.x = r.x + amount; | |
4520 res.y = r.y + amount; | |
4521 res.w = r.w - 2 * amount; | |
4522 res.h = r.h - 2 * amount; | |
4523 return res; | |
4524 } | |
4525 | |
4526 NK_INTERN struct nk_rect | |
4527 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) | |
4528 { | |
4529 r.w = NK_MAX(r.w, 2 * pad.x); | |
4530 r.h = NK_MAX(r.h, 2 * pad.y); | |
4531 r.x += pad.x; r.y += pad.y; | |
4532 r.w -= 2 * pad.x; | |
4533 r.h -= 2 * pad.y; | |
4534 return r; | |
4535 } | |
4536 | |
4537 NK_API struct nk_vec2 | |
4538 nk_vec2(float x, float y) | |
4539 { | |
4540 struct nk_vec2 ret; | |
4541 ret.x = x; ret.y = y; | |
4542 return ret; | |
4543 } | |
4544 | |
4545 NK_API struct nk_vec2 | |
4546 nk_vec2i(int x, int y) | |
4547 { | |
4548 struct nk_vec2 ret; | |
4549 ret.x = (float)x; | |
4550 ret.y = (float)y; | |
4551 return ret; | |
4552 } | |
4553 | |
4554 NK_API struct nk_vec2 | |
4555 nk_vec2v(const float *v) | |
4556 { | |
4557 return nk_vec2(v[0], v[1]); | |
4558 } | |
4559 | |
4560 NK_API struct nk_vec2 | |
4561 nk_vec2iv(const int *v) | |
4562 { | |
4563 return nk_vec2i(v[0], v[1]); | |
4564 } | |
4565 | |
4566 /* | |
4567 * ============================================================== | |
4568 * | |
4569 * UTIL | |
4570 * | |
4571 * =============================================================== | |
4572 */ | |
4573 NK_INTERN int nk_str_match_here(const char *regexp, const char *text); | |
4574 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); | |
4575 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} | |
4576 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} | |
4577 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} | |
4578 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} | |
4579 | |
4580 NK_INTERN void* | |
4581 nk_memcopy(void *dst0, const void *src0, nk_size length) | |
4582 { | |
4583 nk_ptr t; | |
4584 char *dst = (char*)dst0; | |
4585 const char *src = (const char*)src0; | |
4586 if (length == 0 || dst == src) | |
4587 goto done; | |
4588 | |
4589 #define nk_word int | |
4590 #define nk_wsize sizeof(nk_word) | |
4591 #define nk_wmask (nk_wsize-1) | |
4592 #define NK_TLOOP(s) if (t) NK_TLOOP1(s) | |
4593 #define NK_TLOOP1(s) do { s; } while (--t) | |
4594 | |
4595 if (dst < src) { | |
4596 t = (nk_ptr)src; /* only need low bits */ | |
4597 if ((t | (nk_ptr)dst) & nk_wmask) { | |
4598 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) | |
4599 t = length; | |
4600 else | |
4601 t = nk_wsize - (t & nk_wmask); | |
4602 length -= t; | |
4603 NK_TLOOP1(*dst++ = *src++); | |
4604 } | |
4605 t = length / nk_wsize; | |
4606 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; | |
4607 src += nk_wsize; dst += nk_wsize); | |
4608 t = length & nk_wmask; | |
4609 NK_TLOOP(*dst++ = *src++); | |
4610 } else { | |
4611 src += length; | |
4612 dst += length; | |
4613 t = (nk_ptr)src; | |
4614 if ((t | (nk_ptr)dst) & nk_wmask) { | |
4615 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) | |
4616 t = length; | |
4617 else | |
4618 t &= nk_wmask; | |
4619 length -= t; | |
4620 NK_TLOOP1(*--dst = *--src); | |
4621 } | |
4622 t = length / nk_wsize; | |
4623 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; | |
4624 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); | |
4625 t = length & nk_wmask; | |
4626 NK_TLOOP(*--dst = *--src); | |
4627 } | |
4628 #undef nk_word | |
4629 #undef nk_wsize | |
4630 #undef nk_wmask | |
4631 #undef NK_TLOOP | |
4632 #undef NK_TLOOP1 | |
4633 done: | |
4634 return (dst0); | |
4635 } | |
4636 | |
4637 NK_INTERN void | |
4638 nk_memset(void *ptr, int c0, nk_size size) | |
4639 { | |
4640 #define nk_word unsigned | |
4641 #define nk_wsize sizeof(nk_word) | |
4642 #define nk_wmask (nk_wsize - 1) | |
4643 nk_byte *dst = (nk_byte*)ptr; | |
4644 unsigned c = 0; | |
4645 nk_size t = 0; | |
4646 | |
4647 if ((c = (nk_byte)c0) != 0) { | |
4648 c = (c << 8) | c; /* at least 16-bits */ | |
4649 if (sizeof(unsigned int) > 2) | |
4650 c = (c << 16) | c; /* at least 32-bits*/ | |
4651 } | |
4652 | |
4653 /* too small of a word count */ | |
4654 dst = (nk_byte*)ptr; | |
4655 if (size < 3 * nk_wsize) { | |
4656 while (size--) *dst++ = (nk_byte)c0; | |
4657 return; | |
4658 } | |
4659 | |
4660 /* align destination */ | |
4661 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { | |
4662 t = nk_wsize -t; | |
4663 size -= t; | |
4664 do { | |
4665 *dst++ = (nk_byte)c0; | |
4666 } while (--t != 0); | |
4667 } | |
4668 | |
4669 /* fill word */ | |
4670 t = size / nk_wsize; | |
4671 do { | |
4672 *(nk_word*)((void*)dst) = c; | |
4673 dst += nk_wsize; | |
4674 } while (--t != 0); | |
4675 | |
4676 /* fill trailing bytes */ | |
4677 t = (size & nk_wmask); | |
4678 if (t != 0) { | |
4679 do { | |
4680 *dst++ = (nk_byte)c0; | |
4681 } while (--t != 0); | |
4682 } | |
4683 | |
4684 #undef nk_word | |
4685 #undef nk_wsize | |
4686 #undef nk_wmask | |
4687 } | |
4688 | |
4689 NK_INTERN void | |
4690 nk_zero(void *ptr, nk_size size) | |
4691 { | |
4692 NK_ASSERT(ptr); | |
4693 NK_MEMSET(ptr, 0, size); | |
4694 } | |
4695 | |
4696 NK_API int | |
4697 nk_strlen(const char *str) | |
4698 { | |
4699 int siz = 0; | |
4700 NK_ASSERT(str); | |
4701 while (str && *str++ != '\0') siz++; | |
4702 return siz; | |
4703 } | |
4704 | |
4705 NK_API int | |
4706 nk_strtoi(const char *str, const char **endptr) | |
4707 { | |
4708 int neg = 1; | |
4709 const char *p = str; | |
4710 int value = 0; | |
4711 | |
4712 NK_ASSERT(str); | |
4713 if (!str) return 0; | |
4714 | |
4715 /* skip whitespace */ | |
4716 while (*p == ' ') p++; | |
4717 if (*p == '-') { | |
4718 neg = -1; | |
4719 p++; | |
4720 } | |
4721 while (*p && *p >= '0' && *p <= '9') { | |
4722 value = value * 10 + (int) (*p - '0'); | |
4723 p++; | |
4724 } | |
4725 if (endptr) | |
4726 *endptr = p; | |
4727 return neg*value; | |
4728 } | |
4729 | |
4730 NK_API double | |
4731 nk_strtod(const char *str, const char **endptr) | |
4732 { | |
4733 double m; | |
4734 double neg = 1.0; | |
4735 const char *p = str; | |
4736 double value = 0; | |
4737 double number = 0; | |
4738 | |
4739 NK_ASSERT(str); | |
4740 if (!str) return 0; | |
4741 | |
4742 /* skip whitespace */ | |
4743 while (*p == ' ') p++; | |
4744 if (*p == '-') { | |
4745 neg = -1.0; | |
4746 p++; | |
4747 } | |
4748 | |
4749 while (*p && *p != '.' && *p != 'e') { | |
4750 value = value * 10.0 + (double) (*p - '0'); | |
4751 p++; | |
4752 } | |
4753 | |
4754 if (*p == '.') { | |
4755 p++; | |
4756 for(m = 0.1; *p && *p != 'e'; p++ ) { | |
4757 value = value + (double) (*p - '0') * m; | |
4758 m *= 0.1; | |
4759 } | |
4760 } | |
4761 if (*p == 'e') { | |
4762 int i, pow, div; | |
4763 p++; | |
4764 if (*p == '-') { | |
4765 div = nk_true; | |
4766 p++; | |
4767 } else if (*p == '+') { | |
4768 div = nk_false; | |
4769 p++; | |
4770 } else div = nk_false; | |
4771 | |
4772 for (pow = 0; *p; p++) | |
4773 pow = pow * 10 + (int) (*p - '0'); | |
4774 | |
4775 for (m = 1.0, i = 0; i < pow; i++) | |
4776 m *= 10.0; | |
4777 | |
4778 if (div) | |
4779 value /= m; | |
4780 else value *= m; | |
4781 } | |
4782 number = value * neg; | |
4783 if (endptr) | |
4784 *endptr = p; | |
4785 return number; | |
4786 } | |
4787 | |
4788 NK_API float | |
4789 nk_strtof(const char *str, const char **endptr) | |
4790 { | |
4791 float float_value; | |
4792 double double_value; | |
4793 double_value = NK_STRTOD(str, endptr); | |
4794 float_value = (float)double_value; | |
4795 return float_value; | |
4796 } | |
4797 | |
4798 NK_API int | |
4799 nk_stricmp(const char *s1, const char *s2) | |
4800 { | |
4801 nk_int c1,c2,d; | |
4802 do { | |
4803 c1 = *s1++; | |
4804 c2 = *s2++; | |
4805 d = c1 - c2; | |
4806 while (d) { | |
4807 if (c1 <= 'Z' && c1 >= 'A') { | |
4808 d += ('a' - 'A'); | |
4809 if (!d) break; | |
4810 } | |
4811 if (c2 <= 'Z' && c2 >= 'A') { | |
4812 d -= ('a' - 'A'); | |
4813 if (!d) break; | |
4814 } | |
4815 return ((d >= 0) << 1) - 1; | |
4816 } | |
4817 } while (c1); | |
4818 return 0; | |
4819 } | |
4820 | |
4821 NK_API int | |
4822 nk_stricmpn(const char *s1, const char *s2, int n) | |
4823 { | |
4824 int c1,c2,d; | |
4825 NK_ASSERT(n >= 0); | |
4826 do { | |
4827 c1 = *s1++; | |
4828 c2 = *s2++; | |
4829 if (!n--) return 0; | |
4830 | |
4831 d = c1 - c2; | |
4832 while (d) { | |
4833 if (c1 <= 'Z' && c1 >= 'A') { | |
4834 d += ('a' - 'A'); | |
4835 if (!d) break; | |
4836 } | |
4837 if (c2 <= 'Z' && c2 >= 'A') { | |
4838 d -= ('a' - 'A'); | |
4839 if (!d) break; | |
4840 } | |
4841 return ((d >= 0) << 1) - 1; | |
4842 } | |
4843 } while (c1); | |
4844 return 0; | |
4845 } | |
4846 | |
4847 NK_INTERN int | |
4848 nk_str_match_here(const char *regexp, const char *text) | |
4849 { | |
4850 if (regexp[0] == '\0') | |
4851 return 1; | |
4852 if (regexp[1] == '*') | |
4853 return nk_str_match_star(regexp[0], regexp+2, text); | |
4854 if (regexp[0] == '$' && regexp[1] == '\0') | |
4855 return *text == '\0'; | |
4856 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) | |
4857 return nk_str_match_here(regexp+1, text+1); | |
4858 return 0; | |
4859 } | |
4860 | |
4861 NK_INTERN int | |
4862 nk_str_match_star(int c, const char *regexp, const char *text) | |
4863 { | |
4864 do {/* a '* matches zero or more instances */ | |
4865 if (nk_str_match_here(regexp, text)) | |
4866 return 1; | |
4867 } while (*text != '\0' && (*text++ == c || c == '.')); | |
4868 return 0; | |
4869 } | |
4870 | |
4871 NK_API int | |
4872 nk_strfilter(const char *text, const char *regexp) | |
4873 { | |
4874 /* | |
4875 c matches any literal character c | |
4876 . matches any single character | |
4877 ^ matches the beginning of the input string | |
4878 $ matches the end of the input string | |
4879 * matches zero or more occurrences of the previous character*/ | |
4880 if (regexp[0] == '^') | |
4881 return nk_str_match_here(regexp+1, text); | |
4882 do { /* must look even if string is empty */ | |
4883 if (nk_str_match_here(regexp, text)) | |
4884 return 1; | |
4885 } while (*text++ != '\0'); | |
4886 return 0; | |
4887 } | |
4888 | |
4889 NK_API int | |
4890 nk_strmatch_fuzzy_text(const char *str, int str_len, | |
4891 const char *pattern, int *out_score) | |
4892 { | |
4893 /* Returns true if each character in pattern is found sequentially within str | |
4894 * if found then out_score is also set. Score value has no intrinsic meaning. | |
4895 * Range varies with pattern. Can only compare scores with same search pattern. */ | |
4896 | |
4897 /* ------- scores --------- */ | |
4898 /* bonus for adjacent matches */ | |
4899 #define NK_ADJACENCY_BONUS 5 | |
4900 /* bonus if match occurs after a separator */ | |
4901 #define NK_SEPARATOR_BONUS 10 | |
4902 /* bonus if match is uppercase and prev is lower */ | |
4903 #define NK_CAMEL_BONUS 10 | |
4904 /* penalty applied for every letter in str before the first match */ | |
4905 #define NK_LEADING_LETTER_PENALTY (-3) | |
4906 /* maximum penalty for leading letters */ | |
4907 #define NK_MAX_LEADING_LETTER_PENALTY (-9) | |
4908 /* penalty for every letter that doesn't matter */ | |
4909 #define NK_UNMATCHED_LETTER_PENALTY (-1) | |
4910 | |
4911 /* loop variables */ | |
4912 int score = 0; | |
4913 char const * pattern_iter = pattern; | |
4914 int str_iter = 0; | |
4915 int prev_matched = nk_false; | |
4916 int prev_lower = nk_false; | |
4917 /* true so if first letter match gets separator bonus*/ | |
4918 int prev_separator = nk_true; | |
4919 | |
4920 /* use "best" matched letter if multiple string letters match the pattern */ | |
4921 char const * best_letter = 0; | |
4922 int best_letter_score = 0; | |
4923 | |
4924 /* loop over strings */ | |
4925 NK_ASSERT(str); | |
4926 NK_ASSERT(pattern); | |
4927 if (!str || !str_len || !pattern) return 0; | |
4928 while (str_iter < str_len) | |
4929 { | |
4930 const char pattern_letter = *pattern_iter; | |
4931 const char str_letter = str[str_iter]; | |
4932 | |
4933 int next_match = *pattern_iter != '\0' && | |
4934 nk_to_lower(pattern_letter) == nk_to_lower(str_letter); | |
4935 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter); | |
4936 | |
4937 int advanced = next_match && best_letter; | |
4938 int pattern_repeat = best_letter && *pattern_iter != '\0'; | |
4939 pattern_repeat = pattern_repeat && | |
4940 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); | |
4941 | |
4942 if (advanced || pattern_repeat) { | |
4943 score += best_letter_score; | |
4944 best_letter = 0; | |
4945 best_letter_score = 0; | |
4946 } | |
4947 | |
4948 if (next_match || rematch) | |
4949 { | |
4950 int new_score = 0; | |
4951 /* Apply penalty for each letter before the first pattern match */ | |
4952 if (pattern_iter == pattern) { | |
4953 int count = (int)(&str[str_iter] - str); | |
4954 int penalty = NK_LEADING_LETTER_PENALTY * count; | |
4955 if (penalty < NK_MAX_LEADING_LETTER_PENALTY) | |
4956 penalty = NK_MAX_LEADING_LETTER_PENALTY; | |
4957 | |
4958 score += penalty; | |
4959 } | |
4960 | |
4961 /* apply bonus for consecutive bonuses */ | |
4962 if (prev_matched) | |
4963 new_score += NK_ADJACENCY_BONUS; | |
4964 | |
4965 /* apply bonus for matches after a separator */ | |
4966 if (prev_separator) | |
4967 new_score += NK_SEPARATOR_BONUS; | |
4968 | |
4969 /* apply bonus across camel case boundaries */ | |
4970 if (prev_lower && nk_is_upper(str_letter)) | |
4971 new_score += NK_CAMEL_BONUS; | |
4972 | |
4973 /* update pattern iter IFF the next pattern letter was matched */ | |
4974 if (next_match) | |
4975 ++pattern_iter; | |
4976 | |
4977 /* update best letter in str which may be for a "next" letter or a rematch */ | |
4978 if (new_score >= best_letter_score) { | |
4979 /* apply penalty for now skipped letter */ | |
4980 if (best_letter != 0) | |
4981 score += NK_UNMATCHED_LETTER_PENALTY; | |
4982 | |
4983 best_letter = &str[str_iter]; | |
4984 best_letter_score = new_score; | |
4985 } | |
4986 prev_matched = nk_true; | |
4987 } else { | |
4988 score += NK_UNMATCHED_LETTER_PENALTY; | |
4989 prev_matched = nk_false; | |
4990 } | |
4991 | |
4992 /* separators should be more easily defined */ | |
4993 prev_lower = nk_is_lower(str_letter) != 0; | |
4994 prev_separator = str_letter == '_' || str_letter == ' '; | |
4995 | |
4996 ++str_iter; | |
4997 } | |
4998 | |
4999 /* apply score for last match */ | |
5000 if (best_letter) | |
5001 score += best_letter_score; | |
5002 | |
5003 /* did not match full pattern */ | |
5004 if (*pattern_iter != '\0') | |
5005 return nk_false; | |
5006 | |
5007 if (out_score) | |
5008 *out_score = score; | |
5009 return nk_true; | |
5010 } | |
5011 | |
5012 NK_API int | |
5013 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) | |
5014 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);} | |
5015 | |
5016 NK_INTERN int | |
5017 nk_string_float_limit(char *string, int prec) | |
5018 { | |
5019 int dot = 0; | |
5020 char *c = string; | |
5021 while (*c) { | |
5022 if (*c == '.') { | |
5023 dot = 1; | |
5024 c++; | |
5025 continue; | |
5026 } | |
5027 if (dot == (prec+1)) { | |
5028 *c = 0; | |
5029 break; | |
5030 } | |
5031 if (dot > 0) dot++; | |
5032 c++; | |
5033 } | |
5034 return (int)(c - string); | |
5035 } | |
5036 | |
5037 NK_INTERN double | |
5038 nk_pow(double x, int n) | |
5039 { | |
5040 /* check the sign of n */ | |
5041 double r = 1; | |
5042 int plus = n >= 0; | |
5043 n = (plus) ? n : -n; | |
5044 while (n > 0) { | |
5045 if ((n & 1) == 1) | |
5046 r *= x; | |
5047 n /= 2; | |
5048 x *= x; | |
5049 } | |
5050 return plus ? r : 1.0 / r; | |
5051 } | |
5052 | |
5053 NK_INTERN int | |
5054 nk_ifloord(double x) | |
5055 { | |
5056 x = (double)((int)x - ((x < 0.0) ? 1 : 0)); | |
5057 return (int)x; | |
5058 } | |
5059 | |
5060 NK_INTERN int | |
5061 nk_ifloorf(float x) | |
5062 { | |
5063 x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); | |
5064 return (int)x; | |
5065 } | |
5066 | |
5067 NK_INTERN int | |
5068 nk_iceilf(float x) | |
5069 { | |
5070 if (x >= 0) { | |
5071 int i = (int)x; | |
5072 return (x > i) ? i+1: i; | |
5073 } else { | |
5074 int t = (int)x; | |
5075 float r = x - (float)t; | |
5076 return (r > 0.0f) ? t+1: t; | |
5077 } | |
5078 } | |
5079 | |
5080 NK_INTERN int | |
5081 nk_log10(double n) | |
5082 { | |
5083 int neg; | |
5084 int ret; | |
5085 int exp = 0; | |
5086 | |
5087 neg = (n < 0) ? 1 : 0; | |
5088 ret = (neg) ? (int)-n : (int)n; | |
5089 while ((ret / 10) > 0) { | |
5090 ret /= 10; | |
5091 exp++; | |
5092 } | |
5093 if (neg) exp = -exp; | |
5094 return exp; | |
5095 } | |
5096 | |
5097 NK_INTERN void | |
5098 nk_strrev_ascii(char *s) | |
5099 { | |
5100 int len = nk_strlen(s); | |
5101 int end = len / 2; | |
5102 int i = 0; | |
5103 char t; | |
5104 for (; i < end; ++i) { | |
5105 t = s[i]; | |
5106 s[i] = s[len - 1 - i]; | |
5107 s[len -1 - i] = t; | |
5108 } | |
5109 } | |
5110 | |
5111 NK_INTERN char* | |
5112 nk_itoa(char *s, long n) | |
5113 { | |
5114 long i = 0; | |
5115 if (n == 0) { | |
5116 s[i++] = '0'; | |
5117 s[i] = 0; | |
5118 return s; | |
5119 } | |
5120 if (n < 0) { | |
5121 s[i++] = '-'; | |
5122 n = -n; | |
5123 } | |
5124 while (n > 0) { | |
5125 s[i++] = (char)('0' + (n % 10)); | |
5126 n /= 10; | |
5127 } | |
5128 s[i] = 0; | |
5129 if (s[0] == '-') | |
5130 ++s; | |
5131 | |
5132 nk_strrev_ascii(s); | |
5133 return s; | |
5134 } | |
5135 | |
5136 NK_INTERN char* | |
5137 nk_dtoa(char *s, double n) | |
5138 { | |
5139 int useExp = 0; | |
5140 int digit = 0, m = 0, m1 = 0; | |
5141 char *c = s; | |
5142 int neg = 0; | |
5143 | |
5144 NK_ASSERT(s); | |
5145 if (!s) return 0; | |
5146 | |
5147 if (n == 0.0) { | |
5148 s[0] = '0'; s[1] = '\0'; | |
5149 return s; | |
5150 } | |
5151 | |
5152 neg = (n < 0); | |
5153 if (neg) n = -n; | |
5154 | |
5155 /* calculate magnitude */ | |
5156 m = nk_log10(n); | |
5157 useExp = (m >= 14 || (neg && m >= 9) || m <= -9); | |
5158 if (neg) *(c++) = '-'; | |
5159 | |
5160 /* set up for scientific notation */ | |
5161 if (useExp) { | |
5162 if (m < 0) | |
5163 m -= 1; | |
5164 n = n / (double)nk_pow(10.0, m); | |
5165 m1 = m; | |
5166 m = 0; | |
5167 } | |
5168 if (m < 1.0) { | |
5169 m = 0; | |
5170 } | |
5171 | |
5172 /* convert the number */ | |
5173 while (n > NK_FLOAT_PRECISION || m >= 0) { | |
5174 double weight = nk_pow(10.0, m); | |
5175 if (weight > 0) { | |
5176 double t = (double)n / weight; | |
5177 digit = nk_ifloord(t); | |
5178 n -= ((double)digit * weight); | |
5179 *(c++) = (char)('0' + (char)digit); | |
5180 } | |
5181 if (m == 0 && n > 0) | |
5182 *(c++) = '.'; | |
5183 m--; | |
5184 } | |
5185 | |
5186 if (useExp) { | |
5187 /* convert the exponent */ | |
5188 int i, j; | |
5189 *(c++) = 'e'; | |
5190 if (m1 > 0) { | |
5191 *(c++) = '+'; | |
5192 } else { | |
5193 *(c++) = '-'; | |
5194 m1 = -m1; | |
5195 } | |
5196 m = 0; | |
5197 while (m1 > 0) { | |
5198 *(c++) = (char)('0' + (char)(m1 % 10)); | |
5199 m1 /= 10; | |
5200 m++; | |
5201 } | |
5202 c -= m; | |
5203 for (i = 0, j = m-1; i<j; i++, j--) { | |
5204 /* swap without temporary */ | |
5205 c[i] ^= c[j]; | |
5206 c[j] ^= c[i]; | |
5207 c[i] ^= c[j]; | |
5208 } | |
5209 c += m; | |
5210 } | |
5211 *(c) = '\0'; | |
5212 return s; | |
5213 } | |
5214 | |
5215 #ifdef NK_INCLUDE_STANDARD_VARARGS | |
5216 #ifndef NK_INCLUDE_STANDARD_IO | |
5217 static int | |
5218 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args) | |
5219 { | |
5220 enum nk_arg_type { | |
5221 NK_ARG_TYPE_CHAR, | |
5222 NK_ARG_TYPE_SHORT, | |
5223 NK_ARG_TYPE_DEFAULT, | |
5224 NK_ARG_TYPE_LONG | |
5225 }; | |
5226 enum nk_arg_flags { | |
5227 NK_ARG_FLAG_LEFT = 0x01, | |
5228 NK_ARG_FLAG_PLUS = 0x02, | |
5229 NK_ARG_FLAG_SPACE = 0x04, | |
5230 NK_ARG_FLAG_NUM = 0x10, | |
5231 NK_ARG_FLAG_ZERO = 0x20 | |
5232 }; | |
5233 | |
5234 char number_buffer[NK_MAX_NUMBER_BUFFER]; | |
5235 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT; | |
5236 int precision = NK_DEFAULT; | |
5237 int width = NK_DEFAULT; | |
5238 nk_flags flag = 0; | |
5239 | |
5240 int len = 0; | |
5241 int result = -1; | |
5242 const char *iter = fmt; | |
5243 | |
5244 NK_ASSERT(buf); | |
5245 NK_ASSERT(buf_size); | |
5246 if (!buf || !buf_size || !fmt) return 0; | |
5247 for (iter = fmt; *iter && len < buf_size; iter++) { | |
5248 /* copy all non-format characters */ | |
5249 while (*iter && (*iter != '%') && (len < buf_size)) | |
5250 buf[len++] = *iter++; | |
5251 if (!(*iter) || len >= buf_size) break; | |
5252 iter++; | |
5253 | |
5254 /* flag arguments */ | |
5255 while (*iter) { | |
5256 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; | |
5257 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; | |
5258 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; | |
5259 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; | |
5260 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; | |
5261 else break; | |
5262 iter++; | |
5263 } | |
5264 | |
5265 /* width argument */ | |
5266 width = NK_DEFAULT; | |
5267 if (*iter >= '1' && *iter <= '9') { | |
5268 const char *end; | |
5269 width = nk_strtoi(iter, &end); | |
5270 if (end == iter) | |
5271 width = -1; | |
5272 else iter = end; | |
5273 } else if (*iter == '*') { | |
5274 width = va_arg(args, int); | |
5275 iter++; | |
5276 } | |
5277 | |
5278 /* precision argument */ | |
5279 precision = NK_DEFAULT; | |
5280 if (*iter == '.') { | |
5281 iter++; | |
5282 if (*iter == '*') { | |
5283 precision = va_arg(args, int); | |
5284 iter++; | |
5285 } else { | |
5286 const char *end; | |
5287 precision = nk_strtoi(iter, &end); | |
5288 if (end == iter) | |
5289 precision = -1; | |
5290 else iter = end; | |
5291 } | |
5292 } | |
5293 | |
5294 /* length modifier */ | |
5295 if (*iter == 'h') { | |
5296 if (*(iter+1) == 'h') { | |
5297 arg_type = NK_ARG_TYPE_CHAR; | |
5298 iter++; | |
5299 } else arg_type = NK_ARG_TYPE_SHORT; | |
5300 iter++; | |
5301 } else if (*iter == 'l') { | |
5302 arg_type = NK_ARG_TYPE_LONG; | |
5303 iter++; | |
5304 } else arg_type = NK_ARG_TYPE_DEFAULT; | |
5305 | |
5306 /* specifier */ | |
5307 if (*iter == '%') { | |
5308 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); | |
5309 NK_ASSERT(precision == NK_DEFAULT); | |
5310 NK_ASSERT(width == NK_DEFAULT); | |
5311 if (len < buf_size) | |
5312 buf[len++] = '%'; | |
5313 } else if (*iter == 's') { | |
5314 /* string */ | |
5315 const char *str = va_arg(args, const char*); | |
5316 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); | |
5317 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); | |
5318 NK_ASSERT(precision == NK_DEFAULT); | |
5319 NK_ASSERT(width == NK_DEFAULT); | |
5320 if (str == buf) return -1; | |
5321 while (str && *str && len < buf_size) | |
5322 buf[len++] = *str++; | |
5323 } else if (*iter == 'n') { | |
5324 /* current length callback */ | |
5325 signed int *n = va_arg(args, int*); | |
5326 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); | |
5327 NK_ASSERT(precision == NK_DEFAULT); | |
5328 NK_ASSERT(width == NK_DEFAULT); | |
5329 if (n) *n = len; | |
5330 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { | |
5331 /* signed integer */ | |
5332 long value = 0; | |
5333 const char *num_iter; | |
5334 int num_len, num_print, padding; | |
5335 int cur_precision = NK_MAX(precision, 1); | |
5336 int cur_width = NK_MAX(width, 0); | |
5337 | |
5338 /* retrieve correct value type */ | |
5339 if (arg_type == NK_ARG_TYPE_CHAR) | |
5340 value = (signed char)va_arg(args, int); | |
5341 else if (arg_type == NK_ARG_TYPE_SHORT) | |
5342 value = (signed short)va_arg(args, int); | |
5343 else if (arg_type == NK_ARG_TYPE_LONG) | |
5344 value = va_arg(args, signed long); | |
5345 else if (*iter == 'c') | |
5346 value = (unsigned char)va_arg(args, int); | |
5347 else value = va_arg(args, signed int); | |
5348 | |
5349 /* convert number to string */ | |
5350 nk_itoa(number_buffer, value); | |
5351 num_len = nk_strlen(number_buffer); | |
5352 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); | |
5353 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) | |
5354 padding = NK_MAX(padding-1, 0); | |
5355 | |
5356 /* fill left padding up to a total of `width` characters */ | |
5357 if (!(flag & NK_ARG_FLAG_LEFT)) { | |
5358 while (padding-- > 0 && (len < buf_size)) { | |
5359 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) | |
5360 buf[len++] = '0'; | |
5361 else buf[len++] = ' '; | |
5362 } | |
5363 } | |
5364 | |
5365 /* copy string value representation into buffer */ | |
5366 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) | |
5367 buf[len++] = '+'; | |
5368 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) | |
5369 buf[len++] = ' '; | |
5370 | |
5371 /* fill up to precision number of digits with '0' */ | |
5372 num_print = NK_MAX(cur_precision, num_len); | |
5373 while (precision && (num_print > num_len) && (len < buf_size)) { | |
5374 buf[len++] = '0'; | |
5375 num_print--; | |
5376 } | |
5377 | |
5378 /* copy string value representation into buffer */ | |
5379 num_iter = number_buffer; | |
5380 while (precision && *num_iter && len < buf_size) | |
5381 buf[len++] = *num_iter++; | |
5382 | |
5383 /* fill right padding up to width characters */ | |
5384 if (flag & NK_ARG_FLAG_LEFT) { | |
5385 while ((padding-- > 0) && (len < buf_size)) | |
5386 buf[len++] = ' '; | |
5387 } | |
5388 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { | |
5389 /* unsigned integer */ | |
5390 unsigned long value = 0; | |
5391 int num_len = 0, num_print, padding = 0; | |
5392 int cur_precision = NK_MAX(precision, 1); | |
5393 int cur_width = NK_MAX(width, 0); | |
5394 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; | |
5395 | |
5396 /* print oct/hex/dec value */ | |
5397 const char *upper_output_format = "0123456789ABCDEF"; | |
5398 const char *lower_output_format = "0123456789abcdef"; | |
5399 const char *output_format = (*iter == 'x') ? | |
5400 lower_output_format: upper_output_format; | |
5401 | |
5402 /* retrieve correct value type */ | |
5403 if (arg_type == NK_ARG_TYPE_CHAR) | |
5404 value = (unsigned char)va_arg(args, int); | |
5405 else if (arg_type == NK_ARG_TYPE_SHORT) | |
5406 value = (unsigned short)va_arg(args, int); | |
5407 else if (arg_type == NK_ARG_TYPE_LONG) | |
5408 value = va_arg(args, unsigned long); | |
5409 else value = va_arg(args, unsigned int); | |
5410 | |
5411 do { | |
5412 /* convert decimal number into hex/oct number */ | |
5413 int digit = output_format[value % base]; | |
5414 if (num_len < NK_MAX_NUMBER_BUFFER) | |
5415 number_buffer[num_len++] = (char)digit; | |
5416 value /= base; | |
5417 } while (value > 0); | |
5418 | |
5419 num_print = NK_MAX(cur_precision, num_len); | |
5420 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); | |
5421 if (flag & NK_ARG_FLAG_NUM) | |
5422 padding = NK_MAX(padding-1, 0); | |
5423 | |
5424 /* fill left padding up to a total of `width` characters */ | |
5425 if (!(flag & NK_ARG_FLAG_LEFT)) { | |
5426 while ((padding-- > 0) && (len < buf_size)) { | |
5427 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) | |
5428 buf[len++] = '0'; | |
5429 else buf[len++] = ' '; | |
5430 } | |
5431 } | |
5432 | |
5433 /* fill up to precision number of digits */ | |
5434 if (num_print && (flag & NK_ARG_FLAG_NUM)) { | |
5435 if ((*iter == 'o') && (len < buf_size)) { | |
5436 buf[len++] = '0'; | |
5437 } else if ((*iter == 'x') && ((len+1) < buf_size)) { | |
5438 buf[len++] = '0'; | |
5439 buf[len++] = 'x'; | |
5440 } else if ((*iter == 'X') && ((len+1) < buf_size)) { | |
5441 buf[len++] = '0'; | |
5442 buf[len++] = 'X'; | |
5443 } | |
5444 } | |
5445 while (precision && (num_print > num_len) && (len < buf_size)) { | |
5446 buf[len++] = '0'; | |
5447 num_print--; | |
5448 } | |
5449 | |
5450 /* reverse number direction */ | |
5451 while (num_len > 0) { | |
5452 if (precision && (len < buf_size)) | |
5453 buf[len++] = number_buffer[num_len-1]; | |
5454 num_len--; | |
5455 } | |
5456 | |
5457 /* fill right padding up to width characters */ | |
5458 if (flag & NK_ARG_FLAG_LEFT) { | |
5459 while ((padding-- > 0) && (len < buf_size)) | |
5460 buf[len++] = ' '; | |
5461 } | |
5462 } else if (*iter == 'f') { | |
5463 /* floating point */ | |
5464 const char *num_iter; | |
5465 int cur_precision = (precision < 0) ? 6: precision; | |
5466 int prefix, cur_width = NK_MAX(width, 0); | |
5467 double value = va_arg(args, double); | |
5468 int num_len = 0, frac_len = 0, dot = 0; | |
5469 int padding = 0; | |
5470 | |
5471 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); | |
5472 NK_DTOA(number_buffer, value); | |
5473 num_len = nk_strlen(number_buffer); | |
5474 | |
5475 /* calculate padding */ | |
5476 num_iter = number_buffer; | |
5477 while (*num_iter && *num_iter != '.') | |
5478 num_iter++; | |
5479 | |
5480 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; | |
5481 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); | |
5482 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) | |
5483 padding = NK_MAX(padding-1, 0); | |
5484 | |
5485 /* fill left padding up to a total of `width` characters */ | |
5486 if (!(flag & NK_ARG_FLAG_LEFT)) { | |
5487 while (padding-- > 0 && (len < buf_size)) { | |
5488 if (flag & NK_ARG_FLAG_ZERO) | |
5489 buf[len++] = '0'; | |
5490 else buf[len++] = ' '; | |
5491 } | |
5492 } | |
5493 | |
5494 /* copy string value representation into buffer */ | |
5495 num_iter = number_buffer; | |
5496 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) | |
5497 buf[len++] = '+'; | |
5498 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) | |
5499 buf[len++] = ' '; | |
5500 while (*num_iter) { | |
5501 if (dot) frac_len++; | |
5502 if (len < buf_size) | |
5503 buf[len++] = *num_iter; | |
5504 if (*num_iter == '.') dot = 1; | |
5505 if (frac_len >= cur_precision) break; | |
5506 num_iter++; | |
5507 } | |
5508 | |
5509 /* fill number up to precision */ | |
5510 while (frac_len < cur_precision) { | |
5511 if (!dot && len < buf_size) { | |
5512 buf[len++] = '.'; | |
5513 dot = 1; | |
5514 } | |
5515 if (len < buf_size) | |
5516 buf[len++] = '0'; | |
5517 frac_len++; | |
5518 } | |
5519 | |
5520 /* fill right padding up to width characters */ | |
5521 if (flag & NK_ARG_FLAG_LEFT) { | |
5522 while ((padding-- > 0) && (len < buf_size)) | |
5523 buf[len++] = ' '; | |
5524 } | |
5525 } else { | |
5526 /* Specifier not supported: g,G,e,E,p,z */ | |
5527 NK_ASSERT(0 && "specifier is not supported!"); | |
5528 return result; | |
5529 } | |
5530 } | |
5531 buf[(len >= buf_size)?(buf_size-1):len] = 0; | |
5532 result = (len >= buf_size)?-1:len; | |
5533 return result; | |
5534 } | |
5535 #endif | |
5536 | |
5537 NK_INTERN int | |
5538 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) | |
5539 { | |
5540 int result = -1; | |
5541 NK_ASSERT(buf); | |
5542 NK_ASSERT(buf_size); | |
5543 if (!buf || !buf_size || !fmt) return 0; | |
5544 #ifdef NK_INCLUDE_STANDARD_IO | |
5545 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); | |
5546 result = (result >= buf_size) ? -1: result; | |
5547 buf[buf_size-1] = 0; | |
5548 #else | |
5549 result = nk_vsnprintf(buf, buf_size, fmt, args); | |
5550 #endif | |
5551 return result; | |
5552 } | |
5553 #endif | |
5554 | |
5555 NK_API nk_hash | |
5556 nk_murmur_hash(const void * key, int len, nk_hash seed) | |
5557 { | |
5558 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ | |
5559 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) | |
5560 union {const nk_uint *i; const nk_byte *b;} conv = {0}; | |
5561 const nk_byte *data = (const nk_byte*)key; | |
5562 const int nblocks = len/4; | |
5563 nk_uint h1 = seed; | |
5564 const nk_uint c1 = 0xcc9e2d51; | |
5565 const nk_uint c2 = 0x1b873593; | |
5566 const nk_byte *tail; | |
5567 const nk_uint *blocks; | |
5568 nk_uint k1; | |
5569 int i; | |
5570 | |
5571 /* body */ | |
5572 if (!key) return 0; | |
5573 conv.b = (data + nblocks*4); | |
5574 blocks = (const nk_uint*)conv.i; | |
5575 for (i = -nblocks; i; ++i) { | |
5576 k1 = blocks[i]; | |
5577 k1 *= c1; | |
5578 k1 = NK_ROTL(k1,15); | |
5579 k1 *= c2; | |
5580 | |
5581 h1 ^= k1; | |
5582 h1 = NK_ROTL(h1,13); | |
5583 h1 = h1*5+0xe6546b64; | |
5584 } | |
5585 | |
5586 /* tail */ | |
5587 tail = (const nk_byte*)(data + nblocks*4); | |
5588 k1 = 0; | |
5589 switch (len & 3) { | |
5590 case 3: k1 ^= (nk_uint)(tail[2] << 16); | |
5591 case 2: k1 ^= (nk_uint)(tail[1] << 8u); | |
5592 case 1: k1 ^= tail[0]; | |
5593 k1 *= c1; | |
5594 k1 = NK_ROTL(k1,15); | |
5595 k1 *= c2; | |
5596 h1 ^= k1; | |
5597 default: break; | |
5598 } | |
5599 | |
5600 /* finalization */ | |
5601 h1 ^= (nk_uint)len; | |
5602 /* fmix32 */ | |
5603 h1 ^= h1 >> 16; | |
5604 h1 *= 0x85ebca6b; | |
5605 h1 ^= h1 >> 13; | |
5606 h1 *= 0xc2b2ae35; | |
5607 h1 ^= h1 >> 16; | |
5608 | |
5609 #undef NK_ROTL | |
5610 return h1; | |
5611 } | |
5612 | |
5613 #ifdef NK_INCLUDE_STANDARD_IO | |
5614 NK_INTERN char* | |
5615 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) | |
5616 { | |
5617 char *buf; | |
5618 FILE *fd; | |
5619 long ret; | |
5620 | |
5621 NK_ASSERT(path); | |
5622 NK_ASSERT(siz); | |
5623 NK_ASSERT(alloc); | |
5624 if (!path || !siz || !alloc) | |
5625 return 0; | |
5626 | |
5627 fd = fopen(path, "rb"); | |
5628 if (!fd) return 0; | |
5629 fseek(fd, 0, SEEK_END); | |
5630 ret = ftell(fd); | |
5631 if (ret < 0) { | |
5632 fclose(fd); | |
5633 return 0; | |
5634 } | |
5635 *siz = (nk_size)ret; | |
5636 fseek(fd, 0, SEEK_SET); | |
5637 buf = (char*)alloc->alloc(alloc->userdata,0, *siz); | |
5638 NK_ASSERT(buf); | |
5639 if (!buf) { | |
5640 fclose(fd); | |
5641 return 0; | |
5642 } | |
5643 *siz = (nk_size)fread(buf, *siz, 1, fd); | |
5644 fclose(fd); | |
5645 return buf; | |
5646 } | |
5647 #endif | |
5648 | |
5649 /* | |
5650 * ============================================================== | |
5651 * | |
5652 * COLOR | |
5653 * | |
5654 * =============================================================== | |
5655 */ | |
5656 NK_INTERN int | |
5657 nk_parse_hex(const char *p, int length) | |
5658 { | |
5659 int i = 0; | |
5660 int len = 0; | |
5661 while (len < length) { | |
5662 i <<= 4; | |
5663 if (p[len] >= 'a' && p[len] <= 'f') | |
5664 i += ((p[len] - 'a') + 10); | |
5665 else if (p[len] >= 'A' && p[len] <= 'F') | |
5666 i += ((p[len] - 'A') + 10); | |
5667 else i += (p[len] - '0'); | |
5668 len++; | |
5669 } | |
5670 return i; | |
5671 } | |
5672 | |
5673 NK_API struct nk_color | |
5674 nk_rgba(int r, int g, int b, int a) | |
5675 { | |
5676 struct nk_color ret; | |
5677 ret.r = (nk_byte)NK_CLAMP(0, r, 255); | |
5678 ret.g = (nk_byte)NK_CLAMP(0, g, 255); | |
5679 ret.b = (nk_byte)NK_CLAMP(0, b, 255); | |
5680 ret.a = (nk_byte)NK_CLAMP(0, a, 255); | |
5681 return ret; | |
5682 } | |
5683 | |
5684 NK_API struct nk_color | |
5685 nk_rgb_hex(const char *rgb) | |
5686 { | |
5687 struct nk_color col; | |
5688 const char *c = rgb; | |
5689 if (*c == '#') c++; | |
5690 col.r = (nk_byte)nk_parse_hex(c, 2); | |
5691 col.g = (nk_byte)nk_parse_hex(c+2, 2); | |
5692 col.b = (nk_byte)nk_parse_hex(c+4, 2); | |
5693 col.a = 255; | |
5694 return col; | |
5695 } | |
5696 | |
5697 NK_API struct nk_color | |
5698 nk_rgba_hex(const char *rgb) | |
5699 { | |
5700 struct nk_color col; | |
5701 const char *c = rgb; | |
5702 if (*c == '#') c++; | |
5703 col.r = (nk_byte)nk_parse_hex(c, 2); | |
5704 col.g = (nk_byte)nk_parse_hex(c+2, 2); | |
5705 col.b = (nk_byte)nk_parse_hex(c+4, 2); | |
5706 col.a = (nk_byte)nk_parse_hex(c+6, 2); | |
5707 return col; | |
5708 } | |
5709 | |
5710 NK_API void | |
5711 nk_color_hex_rgba(char *output, struct nk_color col) | |
5712 { | |
5713 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) | |
5714 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); | |
5715 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); | |
5716 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); | |
5717 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); | |
5718 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); | |
5719 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); | |
5720 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); | |
5721 output[7] = (char)NK_TO_HEX((col.a & 0x0F)); | |
5722 output[8] = '\0'; | |
5723 #undef NK_TO_HEX | |
5724 } | |
5725 | |
5726 NK_API void | |
5727 nk_color_hex_rgb(char *output, struct nk_color col) | |
5728 { | |
5729 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) | |
5730 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); | |
5731 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); | |
5732 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); | |
5733 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); | |
5734 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); | |
5735 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); | |
5736 output[6] = '\0'; | |
5737 #undef NK_TO_HEX | |
5738 } | |
5739 | |
5740 NK_API struct nk_color | |
5741 nk_rgba_iv(const int *c) | |
5742 { | |
5743 return nk_rgba(c[0], c[1], c[2], c[3]); | |
5744 } | |
5745 | |
5746 NK_API struct nk_color | |
5747 nk_rgba_bv(const nk_byte *c) | |
5748 { | |
5749 return nk_rgba(c[0], c[1], c[2], c[3]); | |
5750 } | |
5751 | |
5752 NK_API struct nk_color | |
5753 nk_rgb(int r, int g, int b) | |
5754 { | |
5755 struct nk_color ret; | |
5756 ret.r = (nk_byte)NK_CLAMP(0, r, 255); | |
5757 ret.g = (nk_byte)NK_CLAMP(0, g, 255); | |
5758 ret.b = (nk_byte)NK_CLAMP(0, b, 255); | |
5759 ret.a = (nk_byte)255; | |
5760 return ret; | |
5761 } | |
5762 | |
5763 NK_API struct nk_color | |
5764 nk_rgb_iv(const int *c) | |
5765 { | |
5766 return nk_rgb(c[0], c[1], c[2]); | |
5767 } | |
5768 | |
5769 NK_API struct nk_color | |
5770 nk_rgb_bv(const nk_byte* c) | |
5771 { | |
5772 return nk_rgb(c[0], c[1], c[2]); | |
5773 } | |
5774 | |
5775 NK_API struct nk_color | |
5776 nk_rgba_u32(nk_uint in) | |
5777 { | |
5778 struct nk_color ret; | |
5779 ret.r = (in & 0xFF); | |
5780 ret.g = ((in >> 8) & 0xFF); | |
5781 ret.b = ((in >> 16) & 0xFF); | |
5782 ret.a = (nk_byte)((in >> 24) & 0xFF); | |
5783 return ret; | |
5784 } | |
5785 | |
5786 NK_API struct nk_color | |
5787 nk_rgba_f(float r, float g, float b, float a) | |
5788 { | |
5789 struct nk_color ret; | |
5790 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); | |
5791 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); | |
5792 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); | |
5793 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); | |
5794 return ret; | |
5795 } | |
5796 | |
5797 NK_API struct nk_color | |
5798 nk_rgba_fv(const float *c) | |
5799 { | |
5800 return nk_rgba_f(c[0], c[1], c[2], c[3]); | |
5801 } | |
5802 | |
5803 NK_API struct nk_color | |
5804 nk_rgb_f(float r, float g, float b) | |
5805 { | |
5806 struct nk_color ret; | |
5807 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); | |
5808 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); | |
5809 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); | |
5810 ret.a = 255; | |
5811 return ret; | |
5812 } | |
5813 | |
5814 NK_API struct nk_color | |
5815 nk_rgb_fv(const float *c) | |
5816 { | |
5817 return nk_rgb_f(c[0], c[1], c[2]); | |
5818 } | |
5819 | |
5820 NK_API struct nk_color | |
5821 nk_hsv(int h, int s, int v) | |
5822 { | |
5823 return nk_hsva(h, s, v, 255); | |
5824 } | |
5825 | |
5826 NK_API struct nk_color | |
5827 nk_hsv_iv(const int *c) | |
5828 { | |
5829 return nk_hsv(c[0], c[1], c[2]); | |
5830 } | |
5831 | |
5832 NK_API struct nk_color | |
5833 nk_hsv_bv(const nk_byte *c) | |
5834 { | |
5835 return nk_hsv(c[0], c[1], c[2]); | |
5836 } | |
5837 | |
5838 NK_API struct nk_color | |
5839 nk_hsv_f(float h, float s, float v) | |
5840 { | |
5841 return nk_hsva_f(h, s, v, 1.0f); | |
5842 } | |
5843 | |
5844 NK_API struct nk_color | |
5845 nk_hsv_fv(const float *c) | |
5846 { | |
5847 return nk_hsv_f(c[0], c[1], c[2]); | |
5848 } | |
5849 | |
5850 NK_API struct nk_color | |
5851 nk_hsva(int h, int s, int v, int a) | |
5852 { | |
5853 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; | |
5854 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; | |
5855 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; | |
5856 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; | |
5857 return nk_hsva_f(hf, sf, vf, af); | |
5858 } | |
5859 | |
5860 NK_API struct nk_color | |
5861 nk_hsva_iv(const int *c) | |
5862 { | |
5863 return nk_hsva(c[0], c[1], c[2], c[3]); | |
5864 } | |
5865 | |
5866 NK_API struct nk_color | |
5867 nk_hsva_bv(const nk_byte *c) | |
5868 { | |
5869 return nk_hsva(c[0], c[1], c[2], c[3]); | |
5870 } | |
5871 | |
5872 NK_API struct nk_color | |
5873 nk_hsva_f(float h, float s, float v, float a) | |
5874 { | |
5875 struct nk_colorf out = {0,0,0,0}; | |
5876 float p, q, t, f; | |
5877 int i; | |
5878 | |
5879 if (s <= 0.0f) { | |
5880 out.r = v; out.g = v; out.b = v; | |
5881 return nk_rgb_f(out.r, out.g, out.b); | |
5882 } | |
5883 | |
5884 h = h / (60.0f/360.0f); | |
5885 i = (int)h; | |
5886 f = h - (float)i; | |
5887 p = v * (1.0f - s); | |
5888 q = v * (1.0f - (s * f)); | |
5889 t = v * (1.0f - s * (1.0f - f)); | |
5890 | |
5891 switch (i) { | |
5892 case 0: default: out.r = v; out.g = t; out.b = p; break; | |
5893 case 1: out.r = q; out.g = v; out.b = p; break; | |
5894 case 2: out.r = p; out.g = v; out.b = t; break; | |
5895 case 3: out.r = p; out.g = q; out.b = v; break; | |
5896 case 4: out.r = t; out.g = p; out.b = v; break; | |
5897 case 5: out.r = v; out.g = p; out.b = q; break; | |
5898 } | |
5899 return nk_rgba_f(out.r, out.g, out.b, a); | |
5900 } | |
5901 | |
5902 NK_API struct nk_color | |
5903 nk_hsva_fv(const float *c) | |
5904 { | |
5905 return nk_hsva_f(c[0], c[1], c[2], c[3]); | |
5906 } | |
5907 | |
5908 NK_API nk_uint | |
5909 nk_color_u32(struct nk_color in) | |
5910 { | |
5911 nk_uint out = (nk_uint)in.r; | |
5912 out |= ((nk_uint)in.g << 8); | |
5913 out |= ((nk_uint)in.b << 16); | |
5914 out |= ((nk_uint)in.a << 24); | |
5915 return out; | |
5916 } | |
5917 | |
5918 NK_API void | |
5919 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) | |
5920 { | |
5921 NK_STORAGE const float s = 1.0f/255.0f; | |
5922 *r = (float)in.r * s; | |
5923 *g = (float)in.g * s; | |
5924 *b = (float)in.b * s; | |
5925 *a = (float)in.a * s; | |
5926 } | |
5927 | |
5928 NK_API void | |
5929 nk_color_fv(float *c, struct nk_color in) | |
5930 { | |
5931 nk_color_f(&c[0], &c[1], &c[2], &c[3], in); | |
5932 } | |
5933 | |
5934 NK_API void | |
5935 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) | |
5936 { | |
5937 NK_STORAGE const double s = 1.0/255.0; | |
5938 *r = (double)in.r * s; | |
5939 *g = (double)in.g * s; | |
5940 *b = (double)in.b * s; | |
5941 *a = (double)in.a * s; | |
5942 } | |
5943 | |
5944 NK_API void | |
5945 nk_color_dv(double *c, struct nk_color in) | |
5946 { | |
5947 nk_color_d(&c[0], &c[1], &c[2], &c[3], in); | |
5948 } | |
5949 | |
5950 NK_API void | |
5951 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) | |
5952 { | |
5953 float a; | |
5954 nk_color_hsva_f(out_h, out_s, out_v, &a, in); | |
5955 } | |
5956 | |
5957 NK_API void | |
5958 nk_color_hsv_fv(float *out, struct nk_color in) | |
5959 { | |
5960 float a; | |
5961 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); | |
5962 } | |
5963 | |
5964 NK_API void | |
5965 nk_color_hsva_f(float *out_h, float *out_s, | |
5966 float *out_v, float *out_a, struct nk_color in) | |
5967 { | |
5968 float chroma; | |
5969 float K = 0.0f; | |
5970 float r,g,b,a; | |
5971 | |
5972 nk_color_f(&r,&g,&b,&a, in); | |
5973 if (g < b) { | |
5974 const float t = g; g = b; b = t; | |
5975 K = -1.f; | |
5976 } | |
5977 if (r < g) { | |
5978 const float t = r; r = g; g = t; | |
5979 K = -2.f/6.0f - K; | |
5980 } | |
5981 chroma = r - ((g < b) ? g: b); | |
5982 *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f)); | |
5983 *out_s = chroma / (r + 1e-20f); | |
5984 *out_v = r; | |
5985 *out_a = (float)in.a / 255.0f; | |
5986 } | |
5987 | |
5988 NK_API void | |
5989 nk_color_hsva_fv(float *out, struct nk_color in) | |
5990 { | |
5991 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); | |
5992 } | |
5993 | |
5994 NK_API void | |
5995 nk_color_hsva_i(int *out_h, int *out_s, int *out_v, | |
5996 int *out_a, struct nk_color in) | |
5997 { | |
5998 float h,s,v,a; | |
5999 nk_color_hsva_f(&h, &s, &v, &a, in); | |
6000 *out_h = (nk_byte)(h * 255.0f); | |
6001 *out_s = (nk_byte)(s * 255.0f); | |
6002 *out_v = (nk_byte)(v * 255.0f); | |
6003 *out_a = (nk_byte)(a * 255.0f); | |
6004 } | |
6005 | |
6006 NK_API void | |
6007 nk_color_hsva_iv(int *out, struct nk_color in) | |
6008 { | |
6009 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); | |
6010 } | |
6011 | |
6012 NK_API void | |
6013 nk_color_hsva_bv(nk_byte *out, struct nk_color in) | |
6014 { | |
6015 int tmp[4]; | |
6016 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); | |
6017 out[0] = (nk_byte)tmp[0]; | |
6018 out[1] = (nk_byte)tmp[1]; | |
6019 out[2] = (nk_byte)tmp[2]; | |
6020 out[3] = (nk_byte)tmp[3]; | |
6021 } | |
6022 | |
6023 NK_API void | |
6024 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) | |
6025 { | |
6026 int tmp[4]; | |
6027 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); | |
6028 *h = (nk_byte)tmp[0]; | |
6029 *s = (nk_byte)tmp[1]; | |
6030 *v = (nk_byte)tmp[2]; | |
6031 *a = (nk_byte)tmp[3]; | |
6032 } | |
6033 | |
6034 NK_API void | |
6035 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) | |
6036 { | |
6037 int a; | |
6038 nk_color_hsva_i(out_h, out_s, out_v, &a, in); | |
6039 } | |
6040 | |
6041 NK_API void | |
6042 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) | |
6043 { | |
6044 int tmp[4]; | |
6045 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); | |
6046 *out_h = (nk_byte)tmp[0]; | |
6047 *out_s = (nk_byte)tmp[1]; | |
6048 *out_v = (nk_byte)tmp[2]; | |
6049 } | |
6050 | |
6051 NK_API void | |
6052 nk_color_hsv_iv(int *out, struct nk_color in) | |
6053 { | |
6054 nk_color_hsv_i(&out[0], &out[1], &out[2], in); | |
6055 } | |
6056 | |
6057 NK_API void | |
6058 nk_color_hsv_bv(nk_byte *out, struct nk_color in) | |
6059 { | |
6060 int tmp[4]; | |
6061 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); | |
6062 out[0] = (nk_byte)tmp[0]; | |
6063 out[1] = (nk_byte)tmp[1]; | |
6064 out[2] = (nk_byte)tmp[2]; | |
6065 } | |
6066 /* | |
6067 * ============================================================== | |
6068 * | |
6069 * IMAGE | |
6070 * | |
6071 * =============================================================== | |
6072 */ | |
6073 NK_API nk_handle | |
6074 nk_handle_ptr(void *ptr) | |
6075 { | |
6076 nk_handle handle = {0}; | |
6077 handle.ptr = ptr; | |
6078 return handle; | |
6079 } | |
6080 | |
6081 NK_API nk_handle | |
6082 nk_handle_id(int id) | |
6083 { | |
6084 nk_handle handle; | |
6085 nk_zero_struct(handle); | |
6086 handle.id = id; | |
6087 return handle; | |
6088 } | |
6089 | |
6090 NK_API struct nk_image | |
6091 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r) | |
6092 { | |
6093 struct nk_image s; | |
6094 nk_zero(&s, sizeof(s)); | |
6095 s.handle.ptr = ptr; | |
6096 s.w = w; s.h = h; | |
6097 s.region[0] = (unsigned short)r.x; | |
6098 s.region[1] = (unsigned short)r.y; | |
6099 s.region[2] = (unsigned short)r.w; | |
6100 s.region[3] = (unsigned short)r.h; | |
6101 return s; | |
6102 } | |
6103 | |
6104 NK_API struct nk_image | |
6105 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r) | |
6106 { | |
6107 struct nk_image s; | |
6108 nk_zero(&s, sizeof(s)); | |
6109 s.handle.id = id; | |
6110 s.w = w; s.h = h; | |
6111 s.region[0] = (unsigned short)r.x; | |
6112 s.region[1] = (unsigned short)r.y; | |
6113 s.region[2] = (unsigned short)r.w; | |
6114 s.region[3] = (unsigned short)r.h; | |
6115 return s; | |
6116 } | |
6117 | |
6118 NK_API struct nk_image | |
6119 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h, | |
6120 struct nk_rect r) | |
6121 { | |
6122 struct nk_image s; | |
6123 nk_zero(&s, sizeof(s)); | |
6124 s.handle = handle; | |
6125 s.w = w; s.h = h; | |
6126 s.region[0] = (unsigned short)r.x; | |
6127 s.region[1] = (unsigned short)r.y; | |
6128 s.region[2] = (unsigned short)r.w; | |
6129 s.region[3] = (unsigned short)r.h; | |
6130 return s; | |
6131 } | |
6132 | |
6133 NK_API struct nk_image | |
6134 nk_image_handle(nk_handle handle) | |
6135 { | |
6136 struct nk_image s; | |
6137 nk_zero(&s, sizeof(s)); | |
6138 s.handle = handle; | |
6139 s.w = 0; s.h = 0; | |
6140 s.region[0] = 0; | |
6141 s.region[1] = 0; | |
6142 s.region[2] = 0; | |
6143 s.region[3] = 0; | |
6144 return s; | |
6145 } | |
6146 | |
6147 NK_API struct nk_image | |
6148 nk_image_ptr(void *ptr) | |
6149 { | |
6150 struct nk_image s; | |
6151 nk_zero(&s, sizeof(s)); | |
6152 NK_ASSERT(ptr); | |
6153 s.handle.ptr = ptr; | |
6154 s.w = 0; s.h = 0; | |
6155 s.region[0] = 0; | |
6156 s.region[1] = 0; | |
6157 s.region[2] = 0; | |
6158 s.region[3] = 0; | |
6159 return s; | |
6160 } | |
6161 | |
6162 NK_API struct nk_image | |
6163 nk_image_id(int id) | |
6164 { | |
6165 struct nk_image s; | |
6166 nk_zero(&s, sizeof(s)); | |
6167 s.handle.id = id; | |
6168 s.w = 0; s.h = 0; | |
6169 s.region[0] = 0; | |
6170 s.region[1] = 0; | |
6171 s.region[2] = 0; | |
6172 s.region[3] = 0; | |
6173 return s; | |
6174 } | |
6175 | |
6176 NK_API int | |
6177 nk_image_is_subimage(const struct nk_image* img) | |
6178 { | |
6179 NK_ASSERT(img); | |
6180 return !(img->w == 0 && img->h == 0); | |
6181 } | |
6182 | |
6183 NK_INTERN void | |
6184 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, | |
6185 float x1, float y1) | |
6186 { | |
6187 NK_ASSERT(a); | |
6188 NK_ASSERT(clip); | |
6189 clip->x = NK_MAX(a->x, x0); | |
6190 clip->y = NK_MAX(a->y, y0); | |
6191 clip->w = NK_MIN(a->x + a->w, x1) - clip->x; | |
6192 clip->h = NK_MIN(a->y + a->h, y1) - clip->y; | |
6193 clip->w = NK_MAX(0, clip->w); | |
6194 clip->h = NK_MAX(0, clip->h); | |
6195 } | |
6196 | |
6197 NK_API void | |
6198 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, | |
6199 float pad_x, float pad_y, enum nk_heading direction) | |
6200 { | |
6201 float w_half, h_half; | |
6202 NK_ASSERT(result); | |
6203 | |
6204 r.w = NK_MAX(2 * pad_x, r.w); | |
6205 r.h = NK_MAX(2 * pad_y, r.h); | |
6206 r.w = r.w - 2 * pad_x; | |
6207 r.h = r.h - 2 * pad_y; | |
6208 | |
6209 r.x = r.x + pad_x; | |
6210 r.y = r.y + pad_y; | |
6211 | |
6212 w_half = r.w / 2.0f; | |
6213 h_half = r.h / 2.0f; | |
6214 | |
6215 if (direction == NK_UP) { | |
6216 result[0] = nk_vec2(r.x + w_half, r.y); | |
6217 result[1] = nk_vec2(r.x + r.w, r.y + r.h); | |
6218 result[2] = nk_vec2(r.x, r.y + r.h); | |
6219 } else if (direction == NK_RIGHT) { | |
6220 result[0] = nk_vec2(r.x, r.y); | |
6221 result[1] = nk_vec2(r.x + r.w, r.y + h_half); | |
6222 result[2] = nk_vec2(r.x, r.y + r.h); | |
6223 } else if (direction == NK_DOWN) { | |
6224 result[0] = nk_vec2(r.x, r.y); | |
6225 result[1] = nk_vec2(r.x + r.w, r.y); | |
6226 result[2] = nk_vec2(r.x + w_half, r.y + r.h); | |
6227 } else { | |
6228 result[0] = nk_vec2(r.x, r.y + h_half); | |
6229 result[1] = nk_vec2(r.x + r.w, r.y); | |
6230 result[2] = nk_vec2(r.x + r.w, r.y + r.h); | |
6231 } | |
6232 } | |
6233 | |
6234 NK_INTERN int | |
6235 nk_text_clamp(const struct nk_user_font *font, const char *text, | |
6236 int text_len, float space, int *glyphs, float *text_width, | |
6237 nk_rune *sep_list, int sep_count) | |
6238 { | |
6239 int i = 0; | |
6240 int glyph_len = 0; | |
6241 float last_width = 0; | |
6242 nk_rune unicode = 0; | |
6243 float width = 0; | |
6244 int len = 0; | |
6245 int g = 0; | |
6246 float s; | |
6247 | |
6248 int sep_len = 0; | |
6249 int sep_g = 0; | |
6250 float sep_width = 0; | |
6251 sep_count = NK_MAX(sep_count,0); | |
6252 | |
6253 glyph_len = nk_utf_decode(text, &unicode, text_len); | |
6254 while (glyph_len && (width < space) && (len < text_len)) { | |
6255 len += glyph_len; | |
6256 s = font->width(font->userdata, font->height, text, len); | |
6257 for (i = 0; i < sep_count; ++i) { | |
6258 if (unicode != sep_list[i]) continue; | |
6259 sep_width = last_width = width; | |
6260 sep_g = g+1; | |
6261 sep_len = len; | |
6262 break; | |
6263 } | |
6264 if (i == sep_count){ | |
6265 last_width = sep_width = width; | |
6266 sep_g = g+1; | |
6267 } | |
6268 width = s; | |
6269 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); | |
6270 g++; | |
6271 } | |
6272 if (len >= text_len) { | |
6273 *glyphs = g; | |
6274 *text_width = last_width; | |
6275 return len; | |
6276 } else { | |
6277 *glyphs = sep_g; | |
6278 *text_width = sep_width; | |
6279 return (!sep_len) ? len: sep_len; | |
6280 } | |
6281 } | |
6282 | |
6283 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; | |
6284 NK_INTERN struct nk_vec2 | |
6285 nk_text_calculate_text_bounds(const struct nk_user_font *font, | |
6286 const char *begin, int byte_len, float row_height, const char **remaining, | |
6287 struct nk_vec2 *out_offset, int *glyphs, int op) | |
6288 { | |
6289 float line_height = row_height; | |
6290 struct nk_vec2 text_size = nk_vec2(0,0); | |
6291 float line_width = 0.0f; | |
6292 | |
6293 float glyph_width; | |
6294 int glyph_len = 0; | |
6295 nk_rune unicode = 0; | |
6296 int text_len = 0; | |
6297 if (!begin || byte_len <= 0 || !font) | |
6298 return nk_vec2(0,row_height); | |
6299 | |
6300 glyph_len = nk_utf_decode(begin, &unicode, byte_len); | |
6301 if (!glyph_len) return text_size; | |
6302 glyph_width = font->width(font->userdata, font->height, begin, glyph_len); | |
6303 | |
6304 *glyphs = 0; | |
6305 while ((text_len < byte_len) && glyph_len) { | |
6306 if (unicode == '\n') { | |
6307 text_size.x = NK_MAX(text_size.x, line_width); | |
6308 text_size.y += line_height; | |
6309 line_width = 0; | |
6310 *glyphs+=1; | |
6311 if (op == NK_STOP_ON_NEW_LINE) | |
6312 break; | |
6313 | |
6314 text_len++; | |
6315 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); | |
6316 continue; | |
6317 } | |
6318 | |
6319 if (unicode == '\r') { | |
6320 text_len++; | |
6321 *glyphs+=1; | |
6322 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); | |
6323 continue; | |
6324 } | |
6325 | |
6326 *glyphs = *glyphs + 1; | |
6327 text_len += glyph_len; | |
6328 line_width += (float)glyph_width; | |
6329 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); | |
6330 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); | |
6331 continue; | |
6332 } | |
6333 | |
6334 if (text_size.x < line_width) | |
6335 text_size.x = line_width; | |
6336 if (out_offset) | |
6337 *out_offset = nk_vec2(line_width, text_size.y + line_height); | |
6338 if (line_width > 0 || text_size.y == 0.0f) | |
6339 text_size.y += line_height; | |
6340 if (remaining) | |
6341 *remaining = begin+text_len; | |
6342 return text_size; | |
6343 } | |
6344 | |
6345 /* ============================================================== | |
6346 * | |
6347 * UTF-8 | |
6348 * | |
6349 * ===============================================================*/ | |
6350 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; | |
6351 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; | |
6352 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; | |
6353 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; | |
6354 | |
6355 NK_INTERN int | |
6356 nk_utf_validate(nk_rune *u, int i) | |
6357 { | |
6358 NK_ASSERT(u); | |
6359 if (!u) return 0; | |
6360 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || | |
6361 NK_BETWEEN(*u, 0xD800, 0xDFFF)) | |
6362 *u = NK_UTF_INVALID; | |
6363 for (i = 1; *u > nk_utfmax[i]; ++i); | |
6364 return i; | |
6365 } | |
6366 | |
6367 NK_INTERN nk_rune | |
6368 nk_utf_decode_byte(char c, int *i) | |
6369 { | |
6370 NK_ASSERT(i); | |
6371 if (!i) return 0; | |
6372 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { | |
6373 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) | |
6374 return (nk_byte)(c & ~nk_utfmask[*i]); | |
6375 } | |
6376 return 0; | |
6377 } | |
6378 | |
6379 NK_API int | |
6380 nk_utf_decode(const char *c, nk_rune *u, int clen) | |
6381 { | |
6382 int i, j, len, type=0; | |
6383 nk_rune udecoded; | |
6384 | |
6385 NK_ASSERT(c); | |
6386 NK_ASSERT(u); | |
6387 | |
6388 if (!c || !u) return 0; | |
6389 if (!clen) return 0; | |
6390 *u = NK_UTF_INVALID; | |
6391 | |
6392 udecoded = nk_utf_decode_byte(c[0], &len); | |
6393 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) | |
6394 return 1; | |
6395 | |
6396 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { | |
6397 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); | |
6398 if (type != 0) | |
6399 return j; | |
6400 } | |
6401 if (j < len) | |
6402 return 0; | |
6403 *u = udecoded; | |
6404 nk_utf_validate(u, len); | |
6405 return len; | |
6406 } | |
6407 | |
6408 NK_INTERN char | |
6409 nk_utf_encode_byte(nk_rune u, int i) | |
6410 { | |
6411 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); | |
6412 } | |
6413 | |
6414 NK_API int | |
6415 nk_utf_encode(nk_rune u, char *c, int clen) | |
6416 { | |
6417 int len, i; | |
6418 len = nk_utf_validate(&u, 0); | |
6419 if (clen < len || !len || len > NK_UTF_SIZE) | |
6420 return 0; | |
6421 | |
6422 for (i = len - 1; i != 0; --i) { | |
6423 c[i] = nk_utf_encode_byte(u, 0); | |
6424 u >>= 6; | |
6425 } | |
6426 c[0] = nk_utf_encode_byte(u, len); | |
6427 return len; | |
6428 } | |
6429 | |
6430 NK_API int | |
6431 nk_utf_len(const char *str, int len) | |
6432 { | |
6433 const char *text; | |
6434 int glyphs = 0; | |
6435 int text_len; | |
6436 int glyph_len; | |
6437 int src_len = 0; | |
6438 nk_rune unicode; | |
6439 | |
6440 NK_ASSERT(str); | |
6441 if (!str || !len) return 0; | |
6442 | |
6443 text = str; | |
6444 text_len = len; | |
6445 glyph_len = nk_utf_decode(text, &unicode, text_len); | |
6446 while (glyph_len && src_len < len) { | |
6447 glyphs++; | |
6448 src_len = src_len + glyph_len; | |
6449 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); | |
6450 } | |
6451 return glyphs; | |
6452 } | |
6453 | |
6454 NK_API const char* | |
6455 nk_utf_at(const char *buffer, int length, int index, | |
6456 nk_rune *unicode, int *len) | |
6457 { | |
6458 int i = 0; | |
6459 int src_len = 0; | |
6460 int glyph_len = 0; | |
6461 const char *text; | |
6462 int text_len; | |
6463 | |
6464 NK_ASSERT(buffer); | |
6465 NK_ASSERT(unicode); | |
6466 NK_ASSERT(len); | |
6467 | |
6468 if (!buffer || !unicode || !len) return 0; | |
6469 if (index < 0) { | |
6470 *unicode = NK_UTF_INVALID; | |
6471 *len = 0; | |
6472 return 0; | |
6473 } | |
6474 | |
6475 text = buffer; | |
6476 text_len = length; | |
6477 glyph_len = nk_utf_decode(text, unicode, text_len); | |
6478 while (glyph_len) { | |
6479 if (i == index) { | |
6480 *len = glyph_len; | |
6481 break; | |
6482 } | |
6483 | |
6484 i++; | |
6485 src_len = src_len + glyph_len; | |
6486 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); | |
6487 } | |
6488 if (i != index) return 0; | |
6489 return buffer + src_len; | |
6490 } | |
6491 | |
6492 /* ============================================================== | |
6493 * | |
6494 * BUFFER | |
6495 * | |
6496 * ===============================================================*/ | |
6497 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
6498 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size) | |
6499 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);} | |
6500 NK_INTERN void nk_mfree(nk_handle unused, void *ptr) | |
6501 {NK_UNUSED(unused); free(ptr);} | |
6502 | |
6503 NK_API void | |
6504 nk_buffer_init_default(struct nk_buffer *buffer) | |
6505 { | |
6506 struct nk_allocator alloc; | |
6507 alloc.userdata.ptr = 0; | |
6508 alloc.alloc = nk_malloc; | |
6509 alloc.free = nk_mfree; | |
6510 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); | |
6511 } | |
6512 #endif | |
6513 | |
6514 NK_API void | |
6515 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, | |
6516 nk_size initial_size) | |
6517 { | |
6518 NK_ASSERT(b); | |
6519 NK_ASSERT(a); | |
6520 NK_ASSERT(initial_size); | |
6521 if (!b || !a || !initial_size) return; | |
6522 | |
6523 nk_zero(b, sizeof(*b)); | |
6524 b->type = NK_BUFFER_DYNAMIC; | |
6525 b->memory.ptr = a->alloc(a->userdata,0, initial_size); | |
6526 b->memory.size = initial_size; | |
6527 b->size = initial_size; | |
6528 b->grow_factor = 2.0f; | |
6529 b->pool = *a; | |
6530 } | |
6531 | |
6532 NK_API void | |
6533 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) | |
6534 { | |
6535 NK_ASSERT(b); | |
6536 NK_ASSERT(m); | |
6537 NK_ASSERT(size); | |
6538 if (!b || !m || !size) return; | |
6539 | |
6540 nk_zero(b, sizeof(*b)); | |
6541 b->type = NK_BUFFER_FIXED; | |
6542 b->memory.ptr = m; | |
6543 b->memory.size = size; | |
6544 b->size = size; | |
6545 } | |
6546 | |
6547 NK_INTERN void* | |
6548 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, | |
6549 enum nk_buffer_allocation_type type) | |
6550 { | |
6551 void *memory = 0; | |
6552 switch (type) { | |
6553 default: | |
6554 case NK_BUFFER_MAX: | |
6555 case NK_BUFFER_FRONT: | |
6556 if (align) { | |
6557 memory = NK_ALIGN_PTR(unaligned, align); | |
6558 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); | |
6559 } else { | |
6560 memory = unaligned; | |
6561 *alignment = 0; | |
6562 } | |
6563 break; | |
6564 case NK_BUFFER_BACK: | |
6565 if (align) { | |
6566 memory = NK_ALIGN_PTR_BACK(unaligned, align); | |
6567 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); | |
6568 } else { | |
6569 memory = unaligned; | |
6570 *alignment = 0; | |
6571 } | |
6572 break; | |
6573 } | |
6574 return memory; | |
6575 } | |
6576 | |
6577 NK_INTERN void* | |
6578 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) | |
6579 { | |
6580 void *temp; | |
6581 nk_size buffer_size; | |
6582 | |
6583 NK_ASSERT(b); | |
6584 NK_ASSERT(size); | |
6585 if (!b || !size || !b->pool.alloc || !b->pool.free) | |
6586 return 0; | |
6587 | |
6588 buffer_size = b->memory.size; | |
6589 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); | |
6590 NK_ASSERT(temp); | |
6591 if (!temp) return 0; | |
6592 | |
6593 *size = capacity; | |
6594 if (temp != b->memory.ptr) { | |
6595 NK_MEMCPY(temp, b->memory.ptr, buffer_size); | |
6596 b->pool.free(b->pool.userdata, b->memory.ptr); | |
6597 } | |
6598 | |
6599 if (b->size == buffer_size) { | |
6600 /* no back buffer so just set correct size */ | |
6601 b->size = capacity; | |
6602 return temp; | |
6603 } else { | |
6604 /* copy back buffer to the end of the new buffer */ | |
6605 void *dst, *src; | |
6606 nk_size back_size; | |
6607 back_size = buffer_size - b->size; | |
6608 dst = nk_ptr_add(void, temp, capacity - back_size); | |
6609 src = nk_ptr_add(void, temp, b->size); | |
6610 NK_MEMCPY(dst, src, back_size); | |
6611 b->size = capacity - back_size; | |
6612 } | |
6613 return temp; | |
6614 } | |
6615 | |
6616 NK_INTERN void* | |
6617 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, | |
6618 nk_size size, nk_size align) | |
6619 { | |
6620 int full; | |
6621 nk_size alignment; | |
6622 void *unaligned; | |
6623 void *memory; | |
6624 | |
6625 NK_ASSERT(b); | |
6626 NK_ASSERT(size); | |
6627 if (!b || !size) return 0; | |
6628 b->needed += size; | |
6629 | |
6630 /* calculate total size with needed alignment + size */ | |
6631 if (type == NK_BUFFER_FRONT) | |
6632 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); | |
6633 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); | |
6634 memory = nk_buffer_align(unaligned, align, &alignment, type); | |
6635 | |
6636 /* check if buffer has enough memory*/ | |
6637 if (type == NK_BUFFER_FRONT) | |
6638 full = ((b->allocated + size + alignment) > b->size); | |
6639 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated); | |
6640 | |
6641 if (full) { | |
6642 nk_size capacity; | |
6643 if (b->type != NK_BUFFER_DYNAMIC) | |
6644 return 0; | |
6645 NK_ASSERT(b->pool.alloc && b->pool.free); | |
6646 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) | |
6647 return 0; | |
6648 | |
6649 /* buffer is full so allocate bigger buffer if dynamic */ | |
6650 capacity = (nk_size)((float)b->memory.size * b->grow_factor); | |
6651 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); | |
6652 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); | |
6653 if (!b->memory.ptr) return 0; | |
6654 | |
6655 /* align newly allocated pointer */ | |
6656 if (type == NK_BUFFER_FRONT) | |
6657 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); | |
6658 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); | |
6659 memory = nk_buffer_align(unaligned, align, &alignment, type); | |
6660 } | |
6661 if (type == NK_BUFFER_FRONT) | |
6662 b->allocated += size + alignment; | |
6663 else b->size -= (size + alignment); | |
6664 b->needed += alignment; | |
6665 b->calls++; | |
6666 return memory; | |
6667 } | |
6668 | |
6669 NK_API void | |
6670 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, | |
6671 const void *memory, nk_size size, nk_size align) | |
6672 { | |
6673 void *mem = nk_buffer_alloc(b, type, size, align); | |
6674 if (!mem) return; | |
6675 NK_MEMCPY(mem, memory, size); | |
6676 } | |
6677 | |
6678 NK_API void | |
6679 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) | |
6680 { | |
6681 NK_ASSERT(buffer); | |
6682 if (!buffer) return; | |
6683 buffer->marker[type].active = nk_true; | |
6684 if (type == NK_BUFFER_BACK) | |
6685 buffer->marker[type].offset = buffer->size; | |
6686 else buffer->marker[type].offset = buffer->allocated; | |
6687 } | |
6688 | |
6689 NK_API void | |
6690 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) | |
6691 { | |
6692 NK_ASSERT(buffer); | |
6693 if (!buffer) return; | |
6694 if (type == NK_BUFFER_BACK) { | |
6695 /* reset back buffer either back to marker or empty */ | |
6696 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); | |
6697 if (buffer->marker[type].active) | |
6698 buffer->size = buffer->marker[type].offset; | |
6699 else buffer->size = buffer->memory.size; | |
6700 buffer->marker[type].active = nk_false; | |
6701 } else { | |
6702 /* reset front buffer either back to back marker or empty */ | |
6703 buffer->needed -= (buffer->allocated - buffer->marker[type].offset); | |
6704 if (buffer->marker[type].active) | |
6705 buffer->allocated = buffer->marker[type].offset; | |
6706 else buffer->allocated = 0; | |
6707 buffer->marker[type].active = nk_false; | |
6708 } | |
6709 } | |
6710 | |
6711 NK_API void | |
6712 nk_buffer_clear(struct nk_buffer *b) | |
6713 { | |
6714 NK_ASSERT(b); | |
6715 if (!b) return; | |
6716 b->allocated = 0; | |
6717 b->size = b->memory.size; | |
6718 b->calls = 0; | |
6719 b->needed = 0; | |
6720 } | |
6721 | |
6722 NK_API void | |
6723 nk_buffer_free(struct nk_buffer *b) | |
6724 { | |
6725 NK_ASSERT(b); | |
6726 if (!b || !b->memory.ptr) return; | |
6727 if (b->type == NK_BUFFER_FIXED) return; | |
6728 if (!b->pool.free) return; | |
6729 NK_ASSERT(b->pool.free); | |
6730 b->pool.free(b->pool.userdata, b->memory.ptr); | |
6731 } | |
6732 | |
6733 NK_API void | |
6734 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) | |
6735 { | |
6736 NK_ASSERT(b); | |
6737 NK_ASSERT(s); | |
6738 if (!s || !b) return; | |
6739 s->allocated = b->allocated; | |
6740 s->size = b->memory.size; | |
6741 s->needed = b->needed; | |
6742 s->memory = b->memory.ptr; | |
6743 s->calls = b->calls; | |
6744 } | |
6745 | |
6746 NK_API void* | |
6747 nk_buffer_memory(struct nk_buffer *buffer) | |
6748 { | |
6749 NK_ASSERT(buffer); | |
6750 if (!buffer) return 0; | |
6751 return buffer->memory.ptr; | |
6752 } | |
6753 | |
6754 NK_API const void* | |
6755 nk_buffer_memory_const(const struct nk_buffer *buffer) | |
6756 { | |
6757 NK_ASSERT(buffer); | |
6758 if (!buffer) return 0; | |
6759 return buffer->memory.ptr; | |
6760 } | |
6761 | |
6762 NK_API nk_size | |
6763 nk_buffer_total(struct nk_buffer *buffer) | |
6764 { | |
6765 NK_ASSERT(buffer); | |
6766 if (!buffer) return 0; | |
6767 return buffer->memory.size; | |
6768 } | |
6769 | |
6770 /* | |
6771 * ============================================================== | |
6772 * | |
6773 * STRING | |
6774 * | |
6775 * =============================================================== | |
6776 */ | |
6777 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
6778 NK_API void | |
6779 nk_str_init_default(struct nk_str *str) | |
6780 { | |
6781 struct nk_allocator alloc; | |
6782 alloc.userdata.ptr = 0; | |
6783 alloc.alloc = nk_malloc; | |
6784 alloc.free = nk_mfree; | |
6785 nk_buffer_init(&str->buffer, &alloc, 32); | |
6786 str->len = 0; | |
6787 } | |
6788 #endif | |
6789 | |
6790 NK_API void | |
6791 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) | |
6792 { | |
6793 nk_buffer_init(&str->buffer, alloc, size); | |
6794 str->len = 0; | |
6795 } | |
6796 | |
6797 NK_API void | |
6798 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) | |
6799 { | |
6800 nk_buffer_init_fixed(&str->buffer, memory, size); | |
6801 str->len = 0; | |
6802 } | |
6803 | |
6804 NK_API int | |
6805 nk_str_append_text_char(struct nk_str *s, const char *str, int len) | |
6806 { | |
6807 char *mem; | |
6808 NK_ASSERT(s); | |
6809 NK_ASSERT(str); | |
6810 if (!s || !str || !len) return 0; | |
6811 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); | |
6812 if (!mem) return 0; | |
6813 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); | |
6814 s->len += nk_utf_len(str, len); | |
6815 return len; | |
6816 } | |
6817 | |
6818 NK_API int | |
6819 nk_str_append_str_char(struct nk_str *s, const char *str) | |
6820 { | |
6821 return nk_str_append_text_char(s, str, nk_strlen(str)); | |
6822 } | |
6823 | |
6824 NK_API int | |
6825 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) | |
6826 { | |
6827 int i = 0; | |
6828 int byte_len = 0; | |
6829 nk_rune unicode; | |
6830 if (!str || !text || !len) return 0; | |
6831 for (i = 0; i < len; ++i) | |
6832 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); | |
6833 nk_str_append_text_char(str, text, byte_len); | |
6834 return len; | |
6835 } | |
6836 | |
6837 NK_API int | |
6838 nk_str_append_str_utf8(struct nk_str *str, const char *text) | |
6839 { | |
6840 int runes = 0; | |
6841 int byte_len = 0; | |
6842 int num_runes = 0; | |
6843 int glyph_len = 0; | |
6844 nk_rune unicode; | |
6845 if (!str || !text) return 0; | |
6846 | |
6847 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); | |
6848 while (unicode != '\0' && glyph_len) { | |
6849 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); | |
6850 byte_len += glyph_len; | |
6851 num_runes++; | |
6852 } | |
6853 nk_str_append_text_char(str, text, byte_len); | |
6854 return runes; | |
6855 } | |
6856 | |
6857 NK_API int | |
6858 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) | |
6859 { | |
6860 int i = 0; | |
6861 int byte_len = 0; | |
6862 nk_glyph glyph; | |
6863 | |
6864 NK_ASSERT(str); | |
6865 if (!str || !text || !len) return 0; | |
6866 for (i = 0; i < len; ++i) { | |
6867 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); | |
6868 if (!byte_len) break; | |
6869 nk_str_append_text_char(str, glyph, byte_len); | |
6870 } | |
6871 return len; | |
6872 } | |
6873 | |
6874 NK_API int | |
6875 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) | |
6876 { | |
6877 int i = 0; | |
6878 nk_glyph glyph; | |
6879 int byte_len; | |
6880 NK_ASSERT(str); | |
6881 if (!str || !runes) return 0; | |
6882 while (runes[i] != '\0') { | |
6883 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); | |
6884 nk_str_append_text_char(str, glyph, byte_len); | |
6885 i++; | |
6886 } | |
6887 return i; | |
6888 } | |
6889 | |
6890 NK_API int | |
6891 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) | |
6892 { | |
6893 int i; | |
6894 void *mem; | |
6895 char *src; | |
6896 char *dst; | |
6897 | |
6898 int copylen; | |
6899 NK_ASSERT(s); | |
6900 NK_ASSERT(str); | |
6901 NK_ASSERT(len >= 0); | |
6902 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; | |
6903 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && | |
6904 (s->buffer.type == NK_BUFFER_FIXED)) return 0; | |
6905 | |
6906 copylen = (int)s->buffer.allocated - pos; | |
6907 if (!copylen) { | |
6908 nk_str_append_text_char(s, str, len); | |
6909 return 1; | |
6910 } | |
6911 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); | |
6912 if (!mem) return 0; | |
6913 | |
6914 /* memmove */ | |
6915 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); | |
6916 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); | |
6917 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); | |
6918 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); | |
6919 for (i = 0; i < copylen; ++i) *dst-- = *src--; | |
6920 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); | |
6921 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); | |
6922 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); | |
6923 return 1; | |
6924 } | |
6925 | |
6926 NK_API int | |
6927 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) | |
6928 { | |
6929 int glyph_len; | |
6930 nk_rune unicode; | |
6931 const char *begin; | |
6932 const char *buffer; | |
6933 | |
6934 NK_ASSERT(str); | |
6935 NK_ASSERT(cstr); | |
6936 NK_ASSERT(len); | |
6937 if (!str || !cstr || !len) return 0; | |
6938 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); | |
6939 if (!str->len) | |
6940 return nk_str_append_text_char(str, cstr, len); | |
6941 buffer = nk_str_get_const(str); | |
6942 if (!begin) return 0; | |
6943 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); | |
6944 } | |
6945 | |
6946 NK_API int | |
6947 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) | |
6948 { | |
6949 return nk_str_insert_text_utf8(str, pos, text, len); | |
6950 } | |
6951 | |
6952 NK_API int | |
6953 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) | |
6954 { | |
6955 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); | |
6956 } | |
6957 | |
6958 NK_API int | |
6959 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) | |
6960 { | |
6961 int i = 0; | |
6962 int byte_len = 0; | |
6963 nk_rune unicode; | |
6964 | |
6965 NK_ASSERT(str); | |
6966 NK_ASSERT(text); | |
6967 if (!str || !text || !len) return 0; | |
6968 for (i = 0; i < len; ++i) | |
6969 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); | |
6970 nk_str_insert_at_rune(str, pos, text, byte_len); | |
6971 return len; | |
6972 } | |
6973 | |
6974 NK_API int | |
6975 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) | |
6976 { | |
6977 int runes = 0; | |
6978 int byte_len = 0; | |
6979 int num_runes = 0; | |
6980 int glyph_len = 0; | |
6981 nk_rune unicode; | |
6982 if (!str || !text) return 0; | |
6983 | |
6984 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); | |
6985 while (unicode != '\0' && glyph_len) { | |
6986 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); | |
6987 byte_len += glyph_len; | |
6988 num_runes++; | |
6989 } | |
6990 nk_str_insert_at_rune(str, pos, text, byte_len); | |
6991 return runes; | |
6992 } | |
6993 | |
6994 NK_API int | |
6995 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) | |
6996 { | |
6997 int i = 0; | |
6998 int byte_len = 0; | |
6999 nk_glyph glyph; | |
7000 | |
7001 NK_ASSERT(str); | |
7002 if (!str || !runes || !len) return 0; | |
7003 for (i = 0; i < len; ++i) { | |
7004 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); | |
7005 if (!byte_len) break; | |
7006 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); | |
7007 } | |
7008 return len; | |
7009 } | |
7010 | |
7011 NK_API int | |
7012 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) | |
7013 { | |
7014 int i = 0; | |
7015 nk_glyph glyph; | |
7016 int byte_len; | |
7017 NK_ASSERT(str); | |
7018 if (!str || !runes) return 0; | |
7019 while (runes[i] != '\0') { | |
7020 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); | |
7021 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); | |
7022 i++; | |
7023 } | |
7024 return i; | |
7025 } | |
7026 | |
7027 NK_API void | |
7028 nk_str_remove_chars(struct nk_str *s, int len) | |
7029 { | |
7030 NK_ASSERT(s); | |
7031 NK_ASSERT(len >= 0); | |
7032 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; | |
7033 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); | |
7034 s->buffer.allocated -= (nk_size)len; | |
7035 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); | |
7036 } | |
7037 | |
7038 NK_API void | |
7039 nk_str_remove_runes(struct nk_str *str, int len) | |
7040 { | |
7041 int index; | |
7042 const char *begin; | |
7043 const char *end; | |
7044 nk_rune unicode; | |
7045 | |
7046 NK_ASSERT(str); | |
7047 NK_ASSERT(len >= 0); | |
7048 if (!str || len < 0) return; | |
7049 if (len >= str->len) { | |
7050 str->len = 0; | |
7051 return; | |
7052 } | |
7053 | |
7054 index = str->len - len; | |
7055 begin = nk_str_at_rune(str, index, &unicode, &len); | |
7056 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; | |
7057 nk_str_remove_chars(str, (int)(end-begin)+1); | |
7058 } | |
7059 | |
7060 NK_API void | |
7061 nk_str_delete_chars(struct nk_str *s, int pos, int len) | |
7062 { | |
7063 NK_ASSERT(s); | |
7064 if (!s || !len || (nk_size)pos > s->buffer.allocated || | |
7065 (nk_size)(pos + len) > s->buffer.allocated) return; | |
7066 | |
7067 if ((nk_size)(pos + len) < s->buffer.allocated) { | |
7068 /* memmove */ | |
7069 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); | |
7070 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); | |
7071 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); | |
7072 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); | |
7073 s->buffer.allocated -= (nk_size)len; | |
7074 } else nk_str_remove_chars(s, len); | |
7075 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); | |
7076 } | |
7077 | |
7078 NK_API void | |
7079 nk_str_delete_runes(struct nk_str *s, int pos, int len) | |
7080 { | |
7081 char *temp; | |
7082 nk_rune unicode; | |
7083 char *begin; | |
7084 char *end; | |
7085 int unused; | |
7086 | |
7087 NK_ASSERT(s); | |
7088 NK_ASSERT(s->len >= pos + len); | |
7089 if (s->len < pos + len) | |
7090 len = NK_CLAMP(0, (s->len - pos), s->len); | |
7091 if (!len) return; | |
7092 | |
7093 temp = (char *)s->buffer.memory.ptr; | |
7094 begin = nk_str_at_rune(s, pos, &unicode, &unused); | |
7095 if (!begin) return; | |
7096 s->buffer.memory.ptr = begin; | |
7097 end = nk_str_at_rune(s, len, &unicode, &unused); | |
7098 s->buffer.memory.ptr = temp; | |
7099 if (!end) return; | |
7100 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); | |
7101 } | |
7102 | |
7103 NK_API char* | |
7104 nk_str_at_char(struct nk_str *s, int pos) | |
7105 { | |
7106 NK_ASSERT(s); | |
7107 if (!s || pos > (int)s->buffer.allocated) return 0; | |
7108 return nk_ptr_add(char, s->buffer.memory.ptr, pos); | |
7109 } | |
7110 | |
7111 NK_API char* | |
7112 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) | |
7113 { | |
7114 int i = 0; | |
7115 int src_len = 0; | |
7116 int glyph_len = 0; | |
7117 char *text; | |
7118 int text_len; | |
7119 | |
7120 NK_ASSERT(str); | |
7121 NK_ASSERT(unicode); | |
7122 NK_ASSERT(len); | |
7123 | |
7124 if (!str || !unicode || !len) return 0; | |
7125 if (pos < 0) { | |
7126 *unicode = 0; | |
7127 *len = 0; | |
7128 return 0; | |
7129 } | |
7130 | |
7131 text = (char*)str->buffer.memory.ptr; | |
7132 text_len = (int)str->buffer.allocated; | |
7133 glyph_len = nk_utf_decode(text, unicode, text_len); | |
7134 while (glyph_len) { | |
7135 if (i == pos) { | |
7136 *len = glyph_len; | |
7137 break; | |
7138 } | |
7139 | |
7140 i++; | |
7141 src_len = src_len + glyph_len; | |
7142 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); | |
7143 } | |
7144 if (i != pos) return 0; | |
7145 return text + src_len; | |
7146 } | |
7147 | |
7148 NK_API const char* | |
7149 nk_str_at_char_const(const struct nk_str *s, int pos) | |
7150 { | |
7151 NK_ASSERT(s); | |
7152 if (!s || pos > (int)s->buffer.allocated) return 0; | |
7153 return nk_ptr_add(char, s->buffer.memory.ptr, pos); | |
7154 } | |
7155 | |
7156 NK_API const char* | |
7157 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) | |
7158 { | |
7159 int i = 0; | |
7160 int src_len = 0; | |
7161 int glyph_len = 0; | |
7162 char *text; | |
7163 int text_len; | |
7164 | |
7165 NK_ASSERT(str); | |
7166 NK_ASSERT(unicode); | |
7167 NK_ASSERT(len); | |
7168 | |
7169 if (!str || !unicode || !len) return 0; | |
7170 if (pos < 0) { | |
7171 *unicode = 0; | |
7172 *len = 0; | |
7173 return 0; | |
7174 } | |
7175 | |
7176 text = (char*)str->buffer.memory.ptr; | |
7177 text_len = (int)str->buffer.allocated; | |
7178 glyph_len = nk_utf_decode(text, unicode, text_len); | |
7179 while (glyph_len) { | |
7180 if (i == pos) { | |
7181 *len = glyph_len; | |
7182 break; | |
7183 } | |
7184 | |
7185 i++; | |
7186 src_len = src_len + glyph_len; | |
7187 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); | |
7188 } | |
7189 if (i != pos) return 0; | |
7190 return text + src_len; | |
7191 } | |
7192 | |
7193 NK_API nk_rune | |
7194 nk_str_rune_at(const struct nk_str *str, int pos) | |
7195 { | |
7196 int len; | |
7197 nk_rune unicode = 0; | |
7198 nk_str_at_const(str, pos, &unicode, &len); | |
7199 return unicode; | |
7200 } | |
7201 | |
7202 NK_API char* | |
7203 nk_str_get(struct nk_str *s) | |
7204 { | |
7205 NK_ASSERT(s); | |
7206 if (!s || !s->len || !s->buffer.allocated) return 0; | |
7207 return (char*)s->buffer.memory.ptr; | |
7208 } | |
7209 | |
7210 NK_API const char* | |
7211 nk_str_get_const(const struct nk_str *s) | |
7212 { | |
7213 NK_ASSERT(s); | |
7214 if (!s || !s->len || !s->buffer.allocated) return 0; | |
7215 return (const char*)s->buffer.memory.ptr; | |
7216 } | |
7217 | |
7218 NK_API int | |
7219 nk_str_len(struct nk_str *s) | |
7220 { | |
7221 NK_ASSERT(s); | |
7222 if (!s || !s->len || !s->buffer.allocated) return 0; | |
7223 return s->len; | |
7224 } | |
7225 | |
7226 NK_API int | |
7227 nk_str_len_char(struct nk_str *s) | |
7228 { | |
7229 NK_ASSERT(s); | |
7230 if (!s || !s->len || !s->buffer.allocated) return 0; | |
7231 return (int)s->buffer.allocated; | |
7232 } | |
7233 | |
7234 NK_API void | |
7235 nk_str_clear(struct nk_str *str) | |
7236 { | |
7237 NK_ASSERT(str); | |
7238 nk_buffer_clear(&str->buffer); | |
7239 str->len = 0; | |
7240 } | |
7241 | |
7242 NK_API void | |
7243 nk_str_free(struct nk_str *str) | |
7244 { | |
7245 NK_ASSERT(str); | |
7246 nk_buffer_free(&str->buffer); | |
7247 str->len = 0; | |
7248 } | |
7249 | |
7250 /* | |
7251 * ============================================================== | |
7252 * | |
7253 * Command buffer | |
7254 * | |
7255 * =============================================================== | |
7256 */ | |
7257 NK_INTERN void | |
7258 nk_command_buffer_init(struct nk_command_buffer *cmdbuf, | |
7259 struct nk_buffer *buffer, enum nk_command_clipping clip) | |
7260 { | |
7261 NK_ASSERT(cmdbuf); | |
7262 NK_ASSERT(buffer); | |
7263 if (!cmdbuf || !buffer) return; | |
7264 cmdbuf->base = buffer; | |
7265 cmdbuf->use_clipping = clip; | |
7266 cmdbuf->begin = buffer->allocated; | |
7267 cmdbuf->end = buffer->allocated; | |
7268 cmdbuf->last = buffer->allocated; | |
7269 } | |
7270 | |
7271 NK_INTERN void | |
7272 nk_command_buffer_reset(struct nk_command_buffer *buffer) | |
7273 { | |
7274 NK_ASSERT(buffer); | |
7275 if (!buffer) return; | |
7276 buffer->begin = 0; | |
7277 buffer->end = 0; | |
7278 buffer->last = 0; | |
7279 buffer->clip = nk_null_rect; | |
7280 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
7281 buffer->userdata.ptr = 0; | |
7282 #endif | |
7283 } | |
7284 | |
7285 NK_INTERN void* | |
7286 nk_command_buffer_push(struct nk_command_buffer* b, | |
7287 enum nk_command_type t, nk_size size) | |
7288 { | |
7289 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); | |
7290 struct nk_command *cmd; | |
7291 nk_size alignment; | |
7292 void *unaligned; | |
7293 void *memory; | |
7294 | |
7295 NK_ASSERT(b); | |
7296 NK_ASSERT(b->base); | |
7297 if (!b) return 0; | |
7298 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); | |
7299 if (!cmd) return 0; | |
7300 | |
7301 /* make sure the offset to the next command is aligned */ | |
7302 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); | |
7303 unaligned = (nk_byte*)cmd + size; | |
7304 memory = NK_ALIGN_PTR(unaligned, align); | |
7305 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); | |
7306 #ifdef NK_ZERO_COMMAND_MEMORY | |
7307 NK_MEMSET(cmd, 0, size + alignment); | |
7308 #endif | |
7309 | |
7310 cmd->type = t; | |
7311 cmd->next = b->base->allocated + alignment; | |
7312 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
7313 cmd->userdata = b->userdata; | |
7314 #endif | |
7315 b->end = cmd->next; | |
7316 return cmd; | |
7317 } | |
7318 | |
7319 NK_API void | |
7320 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) | |
7321 { | |
7322 struct nk_command_scissor *cmd; | |
7323 NK_ASSERT(b); | |
7324 if (!b) return; | |
7325 | |
7326 b->clip.x = r.x; | |
7327 b->clip.y = r.y; | |
7328 b->clip.w = r.w; | |
7329 b->clip.h = r.h; | |
7330 cmd = (struct nk_command_scissor*) | |
7331 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); | |
7332 | |
7333 if (!cmd) return; | |
7334 cmd->x = (short)r.x; | |
7335 cmd->y = (short)r.y; | |
7336 cmd->w = (unsigned short)NK_MAX(0, r.w); | |
7337 cmd->h = (unsigned short)NK_MAX(0, r.h); | |
7338 } | |
7339 | |
7340 NK_API void | |
7341 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, | |
7342 float x1, float y1, float line_thickness, struct nk_color c) | |
7343 { | |
7344 struct nk_command_line *cmd; | |
7345 NK_ASSERT(b); | |
7346 if (!b || line_thickness <= 0) return; | |
7347 cmd = (struct nk_command_line*) | |
7348 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); | |
7349 if (!cmd) return; | |
7350 cmd->line_thickness = (unsigned short)line_thickness; | |
7351 cmd->begin.x = (short)x0; | |
7352 cmd->begin.y = (short)y0; | |
7353 cmd->end.x = (short)x1; | |
7354 cmd->end.y = (short)y1; | |
7355 cmd->color = c; | |
7356 } | |
7357 | |
7358 NK_API void | |
7359 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, | |
7360 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, | |
7361 float bx, float by, float line_thickness, struct nk_color col) | |
7362 { | |
7363 struct nk_command_curve *cmd; | |
7364 NK_ASSERT(b); | |
7365 if (!b || col.a == 0 || line_thickness <= 0) return; | |
7366 | |
7367 cmd = (struct nk_command_curve*) | |
7368 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); | |
7369 if (!cmd) return; | |
7370 cmd->line_thickness = (unsigned short)line_thickness; | |
7371 cmd->begin.x = (short)ax; | |
7372 cmd->begin.y = (short)ay; | |
7373 cmd->ctrl[0].x = (short)ctrl0x; | |
7374 cmd->ctrl[0].y = (short)ctrl0y; | |
7375 cmd->ctrl[1].x = (short)ctrl1x; | |
7376 cmd->ctrl[1].y = (short)ctrl1y; | |
7377 cmd->end.x = (short)bx; | |
7378 cmd->end.y = (short)by; | |
7379 cmd->color = col; | |
7380 } | |
7381 | |
7382 NK_API void | |
7383 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, | |
7384 float rounding, float line_thickness, struct nk_color c) | |
7385 { | |
7386 struct nk_command_rect *cmd; | |
7387 NK_ASSERT(b); | |
7388 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return; | |
7389 if (b->use_clipping) { | |
7390 const struct nk_rect *clip = &b->clip; | |
7391 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, | |
7392 clip->x, clip->y, clip->w, clip->h)) return; | |
7393 } | |
7394 cmd = (struct nk_command_rect*) | |
7395 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); | |
7396 if (!cmd) return; | |
7397 cmd->rounding = (unsigned short)rounding; | |
7398 cmd->line_thickness = (unsigned short)line_thickness; | |
7399 cmd->x = (short)rect.x; | |
7400 cmd->y = (short)rect.y; | |
7401 cmd->w = (unsigned short)NK_MAX(0, rect.w); | |
7402 cmd->h = (unsigned short)NK_MAX(0, rect.h); | |
7403 cmd->color = c; | |
7404 } | |
7405 | |
7406 NK_API void | |
7407 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, | |
7408 float rounding, struct nk_color c) | |
7409 { | |
7410 struct nk_command_rect_filled *cmd; | |
7411 NK_ASSERT(b); | |
7412 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; | |
7413 if (b->use_clipping) { | |
7414 const struct nk_rect *clip = &b->clip; | |
7415 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, | |
7416 clip->x, clip->y, clip->w, clip->h)) return; | |
7417 } | |
7418 | |
7419 cmd = (struct nk_command_rect_filled*) | |
7420 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); | |
7421 if (!cmd) return; | |
7422 cmd->rounding = (unsigned short)rounding; | |
7423 cmd->x = (short)rect.x; | |
7424 cmd->y = (short)rect.y; | |
7425 cmd->w = (unsigned short)NK_MAX(0, rect.w); | |
7426 cmd->h = (unsigned short)NK_MAX(0, rect.h); | |
7427 cmd->color = c; | |
7428 } | |
7429 | |
7430 NK_API void | |
7431 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, | |
7432 struct nk_color left, struct nk_color top, struct nk_color right, | |
7433 struct nk_color bottom) | |
7434 { | |
7435 struct nk_command_rect_multi_color *cmd; | |
7436 NK_ASSERT(b); | |
7437 if (!b || rect.w == 0 || rect.h == 0) return; | |
7438 if (b->use_clipping) { | |
7439 const struct nk_rect *clip = &b->clip; | |
7440 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, | |
7441 clip->x, clip->y, clip->w, clip->h)) return; | |
7442 } | |
7443 | |
7444 cmd = (struct nk_command_rect_multi_color*) | |
7445 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); | |
7446 if (!cmd) return; | |
7447 cmd->x = (short)rect.x; | |
7448 cmd->y = (short)rect.y; | |
7449 cmd->w = (unsigned short)NK_MAX(0, rect.w); | |
7450 cmd->h = (unsigned short)NK_MAX(0, rect.h); | |
7451 cmd->left = left; | |
7452 cmd->top = top; | |
7453 cmd->right = right; | |
7454 cmd->bottom = bottom; | |
7455 } | |
7456 | |
7457 NK_API void | |
7458 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, | |
7459 float line_thickness, struct nk_color c) | |
7460 { | |
7461 struct nk_command_circle *cmd; | |
7462 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return; | |
7463 if (b->use_clipping) { | |
7464 const struct nk_rect *clip = &b->clip; | |
7465 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) | |
7466 return; | |
7467 } | |
7468 | |
7469 cmd = (struct nk_command_circle*) | |
7470 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); | |
7471 if (!cmd) return; | |
7472 cmd->line_thickness = (unsigned short)line_thickness; | |
7473 cmd->x = (short)r.x; | |
7474 cmd->y = (short)r.y; | |
7475 cmd->w = (unsigned short)NK_MAX(r.w, 0); | |
7476 cmd->h = (unsigned short)NK_MAX(r.h, 0); | |
7477 cmd->color = c; | |
7478 } | |
7479 | |
7480 NK_API void | |
7481 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) | |
7482 { | |
7483 struct nk_command_circle_filled *cmd; | |
7484 NK_ASSERT(b); | |
7485 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; | |
7486 if (b->use_clipping) { | |
7487 const struct nk_rect *clip = &b->clip; | |
7488 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) | |
7489 return; | |
7490 } | |
7491 | |
7492 cmd = (struct nk_command_circle_filled*) | |
7493 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); | |
7494 if (!cmd) return; | |
7495 cmd->x = (short)r.x; | |
7496 cmd->y = (short)r.y; | |
7497 cmd->w = (unsigned short)NK_MAX(r.w, 0); | |
7498 cmd->h = (unsigned short)NK_MAX(r.h, 0); | |
7499 cmd->color = c; | |
7500 } | |
7501 | |
7502 NK_API void | |
7503 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, | |
7504 float a_min, float a_max, float line_thickness, struct nk_color c) | |
7505 { | |
7506 struct nk_command_arc *cmd; | |
7507 if (!b || c.a == 0 || line_thickness <= 0) return; | |
7508 cmd = (struct nk_command_arc*) | |
7509 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); | |
7510 if (!cmd) return; | |
7511 cmd->line_thickness = (unsigned short)line_thickness; | |
7512 cmd->cx = (short)cx; | |
7513 cmd->cy = (short)cy; | |
7514 cmd->r = (unsigned short)radius; | |
7515 cmd->a[0] = a_min; | |
7516 cmd->a[1] = a_max; | |
7517 cmd->color = c; | |
7518 } | |
7519 | |
7520 NK_API void | |
7521 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, | |
7522 float a_min, float a_max, struct nk_color c) | |
7523 { | |
7524 struct nk_command_arc_filled *cmd; | |
7525 NK_ASSERT(b); | |
7526 if (!b || c.a == 0) return; | |
7527 cmd = (struct nk_command_arc_filled*) | |
7528 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); | |
7529 if (!cmd) return; | |
7530 cmd->cx = (short)cx; | |
7531 cmd->cy = (short)cy; | |
7532 cmd->r = (unsigned short)radius; | |
7533 cmd->a[0] = a_min; | |
7534 cmd->a[1] = a_max; | |
7535 cmd->color = c; | |
7536 } | |
7537 | |
7538 NK_API void | |
7539 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, | |
7540 float y1, float x2, float y2, float line_thickness, struct nk_color c) | |
7541 { | |
7542 struct nk_command_triangle *cmd; | |
7543 NK_ASSERT(b); | |
7544 if (!b || c.a == 0 || line_thickness <= 0) return; | |
7545 if (b->use_clipping) { | |
7546 const struct nk_rect *clip = &b->clip; | |
7547 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && | |
7548 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && | |
7549 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) | |
7550 return; | |
7551 } | |
7552 | |
7553 cmd = (struct nk_command_triangle*) | |
7554 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); | |
7555 if (!cmd) return; | |
7556 cmd->line_thickness = (unsigned short)line_thickness; | |
7557 cmd->a.x = (short)x0; | |
7558 cmd->a.y = (short)y0; | |
7559 cmd->b.x = (short)x1; | |
7560 cmd->b.y = (short)y1; | |
7561 cmd->c.x = (short)x2; | |
7562 cmd->c.y = (short)y2; | |
7563 cmd->color = c; | |
7564 } | |
7565 | |
7566 NK_API void | |
7567 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, | |
7568 float y1, float x2, float y2, struct nk_color c) | |
7569 { | |
7570 struct nk_command_triangle_filled *cmd; | |
7571 NK_ASSERT(b); | |
7572 if (!b || c.a == 0) return; | |
7573 if (!b) return; | |
7574 if (b->use_clipping) { | |
7575 const struct nk_rect *clip = &b->clip; | |
7576 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && | |
7577 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && | |
7578 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) | |
7579 return; | |
7580 } | |
7581 | |
7582 cmd = (struct nk_command_triangle_filled*) | |
7583 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); | |
7584 if (!cmd) return; | |
7585 cmd->a.x = (short)x0; | |
7586 cmd->a.y = (short)y0; | |
7587 cmd->b.x = (short)x1; | |
7588 cmd->b.y = (short)y1; | |
7589 cmd->c.x = (short)x2; | |
7590 cmd->c.y = (short)y2; | |
7591 cmd->color = c; | |
7592 } | |
7593 | |
7594 NK_API void | |
7595 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, | |
7596 float line_thickness, struct nk_color col) | |
7597 { | |
7598 int i; | |
7599 nk_size size = 0; | |
7600 struct nk_command_polygon *cmd; | |
7601 | |
7602 NK_ASSERT(b); | |
7603 if (!b || col.a == 0 || line_thickness <= 0) return; | |
7604 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; | |
7605 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); | |
7606 if (!cmd) return; | |
7607 cmd->color = col; | |
7608 cmd->line_thickness = (unsigned short)line_thickness; | |
7609 cmd->point_count = (unsigned short)point_count; | |
7610 for (i = 0; i < point_count; ++i) { | |
7611 cmd->points[i].x = (short)points[i*2]; | |
7612 cmd->points[i].y = (short)points[i*2+1]; | |
7613 } | |
7614 } | |
7615 | |
7616 NK_API void | |
7617 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, | |
7618 struct nk_color col) | |
7619 { | |
7620 int i; | |
7621 nk_size size = 0; | |
7622 struct nk_command_polygon_filled *cmd; | |
7623 | |
7624 NK_ASSERT(b); | |
7625 if (!b || col.a == 0) return; | |
7626 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; | |
7627 cmd = (struct nk_command_polygon_filled*) | |
7628 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); | |
7629 if (!cmd) return; | |
7630 cmd->color = col; | |
7631 cmd->point_count = (unsigned short)point_count; | |
7632 for (i = 0; i < point_count; ++i) { | |
7633 cmd->points[i].x = (short)points[i*2+0]; | |
7634 cmd->points[i].y = (short)points[i*2+1]; | |
7635 } | |
7636 } | |
7637 | |
7638 NK_API void | |
7639 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, | |
7640 float line_thickness, struct nk_color col) | |
7641 { | |
7642 int i; | |
7643 nk_size size = 0; | |
7644 struct nk_command_polyline *cmd; | |
7645 | |
7646 NK_ASSERT(b); | |
7647 if (!b || col.a == 0 || line_thickness <= 0) return; | |
7648 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; | |
7649 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); | |
7650 if (!cmd) return; | |
7651 cmd->color = col; | |
7652 cmd->point_count = (unsigned short)point_count; | |
7653 cmd->line_thickness = (unsigned short)line_thickness; | |
7654 for (i = 0; i < point_count; ++i) { | |
7655 cmd->points[i].x = (short)points[i*2]; | |
7656 cmd->points[i].y = (short)points[i*2+1]; | |
7657 } | |
7658 } | |
7659 | |
7660 NK_API void | |
7661 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, | |
7662 const struct nk_image *img, struct nk_color col) | |
7663 { | |
7664 struct nk_command_image *cmd; | |
7665 NK_ASSERT(b); | |
7666 if (!b) return; | |
7667 if (b->use_clipping) { | |
7668 const struct nk_rect *c = &b->clip; | |
7669 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)) | |
7670 return; | |
7671 } | |
7672 | |
7673 cmd = (struct nk_command_image*) | |
7674 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); | |
7675 if (!cmd) return; | |
7676 cmd->x = (short)r.x; | |
7677 cmd->y = (short)r.y; | |
7678 cmd->w = (unsigned short)NK_MAX(0, r.w); | |
7679 cmd->h = (unsigned short)NK_MAX(0, r.h); | |
7680 cmd->img = *img; | |
7681 cmd->col = col; | |
7682 } | |
7683 | |
7684 NK_API void | |
7685 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r, | |
7686 nk_command_custom_callback cb, nk_handle usr) | |
7687 { | |
7688 struct nk_command_custom *cmd; | |
7689 NK_ASSERT(b); | |
7690 if (!b) return; | |
7691 if (b->use_clipping) { | |
7692 const struct nk_rect *c = &b->clip; | |
7693 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)) | |
7694 return; | |
7695 } | |
7696 | |
7697 cmd = (struct nk_command_custom*) | |
7698 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd)); | |
7699 if (!cmd) return; | |
7700 cmd->x = (short)r.x; | |
7701 cmd->y = (short)r.y; | |
7702 cmd->w = (unsigned short)NK_MAX(0, r.w); | |
7703 cmd->h = (unsigned short)NK_MAX(0, r.h); | |
7704 cmd->callback_data = usr; | |
7705 cmd->callback = cb; | |
7706 } | |
7707 | |
7708 NK_API void | |
7709 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, | |
7710 const char *string, int length, const struct nk_user_font *font, | |
7711 struct nk_color bg, struct nk_color fg) | |
7712 { | |
7713 float text_width = 0; | |
7714 struct nk_command_text *cmd; | |
7715 | |
7716 NK_ASSERT(b); | |
7717 NK_ASSERT(font); | |
7718 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; | |
7719 if (b->use_clipping) { | |
7720 const struct nk_rect *c = &b->clip; | |
7721 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)) | |
7722 return; | |
7723 } | |
7724 | |
7725 /* make sure text fits inside bounds */ | |
7726 text_width = font->width(font->userdata, font->height, string, length); | |
7727 if (text_width > r.w){ | |
7728 int glyphs = 0; | |
7729 float txt_width = (float)text_width; | |
7730 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); | |
7731 } | |
7732 | |
7733 if (!length) return; | |
7734 cmd = (struct nk_command_text*) | |
7735 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); | |
7736 if (!cmd) return; | |
7737 cmd->x = (short)r.x; | |
7738 cmd->y = (short)r.y; | |
7739 cmd->w = (unsigned short)r.w; | |
7740 cmd->h = (unsigned short)r.h; | |
7741 cmd->background = bg; | |
7742 cmd->foreground = fg; | |
7743 cmd->font = font; | |
7744 cmd->length = length; | |
7745 cmd->height = font->height; | |
7746 NK_MEMCPY(cmd->string, string, (nk_size)length); | |
7747 cmd->string[length] = '\0'; | |
7748 } | |
7749 | |
7750 /* ============================================================== | |
7751 * | |
7752 * DRAW LIST | |
7753 * | |
7754 * ===============================================================*/ | |
7755 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
7756 NK_API void | |
7757 nk_draw_list_init(struct nk_draw_list *list) | |
7758 { | |
7759 nk_size i = 0; | |
7760 NK_ASSERT(list); | |
7761 if (!list) return; | |
7762 nk_zero(list, sizeof(*list)); | |
7763 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { | |
7764 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; | |
7765 list->circle_vtx[i].x = (float)NK_COS(a); | |
7766 list->circle_vtx[i].y = (float)NK_SIN(a); | |
7767 } | |
7768 } | |
7769 | |
7770 NK_API void | |
7771 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, | |
7772 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, | |
7773 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa) | |
7774 { | |
7775 NK_ASSERT(canvas); | |
7776 NK_ASSERT(config); | |
7777 NK_ASSERT(cmds); | |
7778 NK_ASSERT(vertices); | |
7779 NK_ASSERT(elements); | |
7780 if (!canvas || !config || !cmds || !vertices || !elements) | |
7781 return; | |
7782 | |
7783 canvas->buffer = cmds; | |
7784 canvas->config = *config; | |
7785 canvas->elements = elements; | |
7786 canvas->vertices = vertices; | |
7787 canvas->line_AA = line_aa; | |
7788 canvas->shape_AA = shape_aa; | |
7789 canvas->clip_rect = nk_null_rect; | |
7790 } | |
7791 | |
7792 NK_API const struct nk_draw_command* | |
7793 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) | |
7794 { | |
7795 nk_byte *memory; | |
7796 nk_size offset; | |
7797 const struct nk_draw_command *cmd; | |
7798 | |
7799 NK_ASSERT(buffer); | |
7800 if (!buffer || !buffer->size || !canvas->cmd_count) | |
7801 return 0; | |
7802 | |
7803 memory = (nk_byte*)buffer->memory.ptr; | |
7804 offset = buffer->memory.size - canvas->cmd_offset; | |
7805 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); | |
7806 return cmd; | |
7807 } | |
7808 | |
7809 NK_API const struct nk_draw_command* | |
7810 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) | |
7811 { | |
7812 nk_size size; | |
7813 nk_size offset; | |
7814 nk_byte *memory; | |
7815 const struct nk_draw_command *end; | |
7816 | |
7817 NK_ASSERT(buffer); | |
7818 NK_ASSERT(canvas); | |
7819 if (!buffer || !canvas) | |
7820 return 0; | |
7821 | |
7822 memory = (nk_byte*)buffer->memory.ptr; | |
7823 size = buffer->memory.size; | |
7824 offset = size - canvas->cmd_offset; | |
7825 end = nk_ptr_add(const struct nk_draw_command, memory, offset); | |
7826 end -= (canvas->cmd_count-1); | |
7827 return end; | |
7828 } | |
7829 | |
7830 NK_API const struct nk_draw_command* | |
7831 nk__draw_list_next(const struct nk_draw_command *cmd, | |
7832 const struct nk_buffer *buffer, const struct nk_draw_list *canvas) | |
7833 { | |
7834 const struct nk_draw_command *end; | |
7835 NK_ASSERT(buffer); | |
7836 NK_ASSERT(canvas); | |
7837 if (!cmd || !buffer || !canvas) | |
7838 return 0; | |
7839 | |
7840 end = nk__draw_list_end(canvas, buffer); | |
7841 if (cmd <= end) return 0; | |
7842 return (cmd-1); | |
7843 } | |
7844 | |
7845 NK_API void | |
7846 nk_draw_list_clear(struct nk_draw_list *list) | |
7847 { | |
7848 NK_ASSERT(list); | |
7849 if (!list) return; | |
7850 if (list->buffer) | |
7851 nk_buffer_clear(list->buffer); | |
7852 if (list->vertices) | |
7853 nk_buffer_clear(list->vertices); | |
7854 if (list->elements) | |
7855 nk_buffer_clear(list->elements); | |
7856 | |
7857 list->element_count = 0; | |
7858 list->vertex_count = 0; | |
7859 list->cmd_offset = 0; | |
7860 list->cmd_count = 0; | |
7861 list->path_count = 0; | |
7862 list->vertices = 0; | |
7863 list->elements = 0; | |
7864 list->clip_rect = nk_null_rect; | |
7865 } | |
7866 | |
7867 NK_INTERN struct nk_vec2* | |
7868 nk_draw_list_alloc_path(struct nk_draw_list *list, int count) | |
7869 { | |
7870 struct nk_vec2 *points; | |
7871 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); | |
7872 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); | |
7873 points = (struct nk_vec2*) | |
7874 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, | |
7875 point_size * (nk_size)count, point_align); | |
7876 | |
7877 if (!points) return 0; | |
7878 if (!list->path_offset) { | |
7879 void *memory = nk_buffer_memory(list->buffer); | |
7880 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); | |
7881 } | |
7882 list->path_count += (unsigned int)count; | |
7883 return points; | |
7884 } | |
7885 | |
7886 NK_INTERN struct nk_vec2 | |
7887 nk_draw_list_path_last(struct nk_draw_list *list) | |
7888 { | |
7889 void *memory; | |
7890 struct nk_vec2 *point; | |
7891 NK_ASSERT(list->path_count); | |
7892 memory = nk_buffer_memory(list->buffer); | |
7893 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); | |
7894 point += (list->path_count-1); | |
7895 return *point; | |
7896 } | |
7897 | |
7898 NK_INTERN struct nk_draw_command* | |
7899 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, | |
7900 nk_handle texture) | |
7901 { | |
7902 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); | |
7903 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); | |
7904 struct nk_draw_command *cmd; | |
7905 | |
7906 NK_ASSERT(list); | |
7907 cmd = (struct nk_draw_command*) | |
7908 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); | |
7909 | |
7910 if (!cmd) return 0; | |
7911 if (!list->cmd_count) { | |
7912 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); | |
7913 nk_size total = nk_buffer_total(list->buffer); | |
7914 memory = nk_ptr_add(nk_byte, memory, total); | |
7915 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); | |
7916 } | |
7917 | |
7918 cmd->elem_count = 0; | |
7919 cmd->clip_rect = clip; | |
7920 cmd->texture = texture; | |
7921 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
7922 cmd->userdata = list->userdata; | |
7923 #endif | |
7924 | |
7925 list->cmd_count++; | |
7926 list->clip_rect = clip; | |
7927 return cmd; | |
7928 } | |
7929 | |
7930 NK_INTERN struct nk_draw_command* | |
7931 nk_draw_list_command_last(struct nk_draw_list *list) | |
7932 { | |
7933 void *memory; | |
7934 nk_size size; | |
7935 struct nk_draw_command *cmd; | |
7936 NK_ASSERT(list->cmd_count); | |
7937 | |
7938 memory = nk_buffer_memory(list->buffer); | |
7939 size = nk_buffer_total(list->buffer); | |
7940 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); | |
7941 return (cmd - (list->cmd_count-1)); | |
7942 } | |
7943 | |
7944 NK_INTERN void | |
7945 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) | |
7946 { | |
7947 NK_ASSERT(list); | |
7948 if (!list) return; | |
7949 if (!list->cmd_count) { | |
7950 nk_draw_list_push_command(list, rect, list->config.null.texture); | |
7951 } else { | |
7952 struct nk_draw_command *prev = nk_draw_list_command_last(list); | |
7953 if (prev->elem_count == 0) | |
7954 prev->clip_rect = rect; | |
7955 nk_draw_list_push_command(list, rect, prev->texture); | |
7956 } | |
7957 } | |
7958 | |
7959 NK_INTERN void | |
7960 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) | |
7961 { | |
7962 NK_ASSERT(list); | |
7963 if (!list) return; | |
7964 if (!list->cmd_count) { | |
7965 nk_draw_list_push_command(list, nk_null_rect, texture); | |
7966 } else { | |
7967 struct nk_draw_command *prev = nk_draw_list_command_last(list); | |
7968 if (prev->elem_count == 0) | |
7969 prev->texture = texture; | |
7970 else if (prev->texture.id != texture.id) | |
7971 nk_draw_list_push_command(list, prev->clip_rect, texture); | |
7972 } | |
7973 } | |
7974 | |
7975 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
7976 NK_API void | |
7977 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) | |
7978 { | |
7979 list->userdata = userdata; | |
7980 } | |
7981 #endif | |
7982 | |
7983 NK_INTERN void* | |
7984 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) | |
7985 { | |
7986 void *vtx; | |
7987 NK_ASSERT(list); | |
7988 if (!list) return 0; | |
7989 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, | |
7990 list->config.vertex_size*count, list->config.vertex_alignment); | |
7991 if (!vtx) return 0; | |
7992 list->vertex_count += (unsigned int)count; | |
7993 return vtx; | |
7994 } | |
7995 | |
7996 NK_INTERN nk_draw_index* | |
7997 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) | |
7998 { | |
7999 nk_draw_index *ids; | |
8000 struct nk_draw_command *cmd; | |
8001 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); | |
8002 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); | |
8003 NK_ASSERT(list); | |
8004 if (!list) return 0; | |
8005 | |
8006 ids = (nk_draw_index*) | |
8007 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); | |
8008 if (!ids) return 0; | |
8009 cmd = nk_draw_list_command_last(list); | |
8010 list->element_count += (unsigned int)count; | |
8011 cmd->elem_count += (unsigned int)count; | |
8012 return ids; | |
8013 } | |
8014 | |
8015 NK_INTERN int | |
8016 nk_draw_vertex_layout_element_is_end_of_layout( | |
8017 const struct nk_draw_vertex_layout_element *element) | |
8018 { | |
8019 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || | |
8020 element->format == NK_FORMAT_COUNT); | |
8021 } | |
8022 | |
8023 NK_INTERN void | |
8024 nk_draw_vertex_color(void *attribute, const float *values, | |
8025 enum nk_draw_vertex_layout_format format) | |
8026 { | |
8027 /* if this triggers you tried to provide a value format for a color */ | |
8028 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); | |
8029 NK_ASSERT(format <= NK_FORMAT_COLOR_END); | |
8030 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; | |
8031 | |
8032 switch (format) { | |
8033 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; | |
8034 case NK_FORMAT_R8G8B8A8: | |
8035 case NK_FORMAT_R8G8B8: { | |
8036 struct nk_color col = nk_rgba_fv(values); | |
8037 NK_MEMCPY(attribute, &col.r, sizeof(col)); | |
8038 } break; | |
8039 case NK_FORMAT_B8G8R8A8: { | |
8040 struct nk_color col = nk_rgba_fv(values); | |
8041 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a); | |
8042 NK_MEMCPY(attribute, &bgra, sizeof(bgra)); | |
8043 } break; | |
8044 case NK_FORMAT_R16G15B16: { | |
8045 nk_ushort col[3]; | |
8046 col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8047 col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8048 col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8049 NK_MEMCPY(attribute, col, sizeof(col)); | |
8050 } break; | |
8051 case NK_FORMAT_R16G15B16A16: { | |
8052 nk_ushort col[4]; | |
8053 col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8054 col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8055 col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8056 col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX); | |
8057 NK_MEMCPY(attribute, col, sizeof(col)); | |
8058 } break; | |
8059 case NK_FORMAT_R32G32B32: { | |
8060 nk_uint col[3]; | |
8061 col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX); | |
8062 col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX); | |
8063 col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX); | |
8064 NK_MEMCPY(attribute, col, sizeof(col)); | |
8065 } break; | |
8066 case NK_FORMAT_R32G32B32A32: { | |
8067 nk_uint col[4]; | |
8068 col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX); | |
8069 col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX); | |
8070 col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX); | |
8071 col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX); | |
8072 NK_MEMCPY(attribute, col, sizeof(col)); | |
8073 } break; | |
8074 case NK_FORMAT_R32G32B32A32_FLOAT: | |
8075 NK_MEMCPY(attribute, values, sizeof(float)*4); | |
8076 break; | |
8077 case NK_FORMAT_R32G32B32A32_DOUBLE: { | |
8078 double col[4]; | |
8079 col[0] = (double)NK_SATURATE(values[0]); | |
8080 col[1] = (double)NK_SATURATE(values[1]); | |
8081 col[2] = (double)NK_SATURATE(values[2]); | |
8082 col[3] = (double)NK_SATURATE(values[3]); | |
8083 NK_MEMCPY(attribute, col, sizeof(col)); | |
8084 } break; | |
8085 case NK_FORMAT_RGB32: | |
8086 case NK_FORMAT_RGBA32: { | |
8087 struct nk_color col = nk_rgba_fv(values); | |
8088 nk_uint color = nk_color_u32(col); | |
8089 NK_MEMCPY(attribute, &color, sizeof(color)); | |
8090 } break; | |
8091 } | |
8092 } | |
8093 | |
8094 NK_INTERN void | |
8095 nk_draw_vertex_element(void *dst, const float *values, int value_count, | |
8096 enum nk_draw_vertex_layout_format format) | |
8097 { | |
8098 int value_index; | |
8099 void *attribute = dst; | |
8100 /* if this triggers you tried to provide a color format for a value */ | |
8101 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); | |
8102 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; | |
8103 for (value_index = 0; value_index < value_count; ++value_index) { | |
8104 switch (format) { | |
8105 default: NK_ASSERT(0 && "invalid vertex layout format"); break; | |
8106 case NK_FORMAT_SCHAR: { | |
8107 char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX); | |
8108 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8109 attribute = (void*)((char*)attribute + sizeof(char)); | |
8110 } break; | |
8111 case NK_FORMAT_SSHORT: { | |
8112 nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX); | |
8113 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8114 attribute = (void*)((char*)attribute + sizeof(value)); | |
8115 } break; | |
8116 case NK_FORMAT_SINT: { | |
8117 nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX); | |
8118 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8119 attribute = (void*)((char*)attribute + sizeof(nk_int)); | |
8120 } break; | |
8121 case NK_FORMAT_UCHAR: { | |
8122 unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX); | |
8123 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8124 attribute = (void*)((char*)attribute + sizeof(unsigned char)); | |
8125 } break; | |
8126 case NK_FORMAT_USHORT: { | |
8127 nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX); | |
8128 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8129 attribute = (void*)((char*)attribute + sizeof(value)); | |
8130 } break; | |
8131 case NK_FORMAT_UINT: { | |
8132 nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX); | |
8133 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8134 attribute = (void*)((char*)attribute + sizeof(nk_uint)); | |
8135 } break; | |
8136 case NK_FORMAT_FLOAT: | |
8137 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); | |
8138 attribute = (void*)((char*)attribute + sizeof(float)); | |
8139 break; | |
8140 case NK_FORMAT_DOUBLE: { | |
8141 double value = (double)values[value_index]; | |
8142 NK_MEMCPY(attribute, &value, sizeof(value)); | |
8143 attribute = (void*)((char*)attribute + sizeof(double)); | |
8144 } break; | |
8145 } | |
8146 } | |
8147 } | |
8148 | |
8149 NK_INTERN void* | |
8150 nk_draw_vertex(void *dst, const struct nk_convert_config *config, | |
8151 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) | |
8152 { | |
8153 void *result = (void*)((char*)dst + config->vertex_size); | |
8154 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; | |
8155 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { | |
8156 void *address = (void*)((char*)dst + elem_iter->offset); | |
8157 switch (elem_iter->attribute) { | |
8158 case NK_VERTEX_ATTRIBUTE_COUNT: | |
8159 default: NK_ASSERT(0 && "wrong element attribute"); | |
8160 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; | |
8161 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; | |
8162 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; | |
8163 } | |
8164 elem_iter++; | |
8165 } | |
8166 return result; | |
8167 } | |
8168 | |
8169 NK_API void | |
8170 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, | |
8171 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, | |
8172 float thickness, enum nk_anti_aliasing aliasing) | |
8173 { | |
8174 nk_size count; | |
8175 int thick_line; | |
8176 struct nk_colorf col; | |
8177 struct nk_colorf col_trans; | |
8178 NK_ASSERT(list); | |
8179 if (!list || points_count < 2) return; | |
8180 | |
8181 color.a = (nk_byte)((float)color.a * list->config.global_alpha); | |
8182 count = points_count; | |
8183 if (!closed) count = points_count-1; | |
8184 thick_line = thickness > 1.0f; | |
8185 | |
8186 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
8187 nk_draw_list_push_userdata(list, list->userdata); | |
8188 #endif | |
8189 | |
8190 color.a = (nk_byte)((float)color.a * list->config.global_alpha); | |
8191 nk_color_fv(&col.r, color); | |
8192 col_trans = col; | |
8193 col_trans.a = 0; | |
8194 | |
8195 if (aliasing == NK_ANTI_ALIASING_ON) { | |
8196 /* ANTI-ALIASED STROKE */ | |
8197 const float AA_SIZE = 1.0f; | |
8198 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); | |
8199 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); | |
8200 | |
8201 /* allocate vertices and elements */ | |
8202 nk_size i1 = 0; | |
8203 nk_size vertex_offset; | |
8204 nk_size index = list->vertex_count; | |
8205 | |
8206 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); | |
8207 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); | |
8208 | |
8209 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); | |
8210 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); | |
8211 | |
8212 nk_size size; | |
8213 struct nk_vec2 *normals, *temp; | |
8214 if (!vtx || !ids) return; | |
8215 | |
8216 /* temporary allocate normals + points */ | |
8217 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); | |
8218 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); | |
8219 size = pnt_size * ((thick_line) ? 5 : 3) * points_count; | |
8220 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); | |
8221 NK_ASSERT(normals); | |
8222 if (!normals) return; | |
8223 temp = normals + points_count; | |
8224 | |
8225 /* make sure vertex pointer is still correct */ | |
8226 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); | |
8227 | |
8228 /* calculate normals */ | |
8229 for (i1 = 0; i1 < count; ++i1) { | |
8230 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); | |
8231 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); | |
8232 float len; | |
8233 | |
8234 /* vec2 inverted length */ | |
8235 len = nk_vec2_len_sqr(diff); | |
8236 if (len != 0.0f) | |
8237 len = nk_inv_sqrt(len); | |
8238 else len = 1.0f; | |
8239 | |
8240 diff = nk_vec2_muls(diff, len); | |
8241 normals[i1].x = diff.y; | |
8242 normals[i1].y = -diff.x; | |
8243 } | |
8244 | |
8245 if (!closed) | |
8246 normals[points_count-1] = normals[points_count-2]; | |
8247 | |
8248 if (!thick_line) { | |
8249 nk_size idx1, i; | |
8250 if (!closed) { | |
8251 struct nk_vec2 d; | |
8252 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); | |
8253 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); | |
8254 d = nk_vec2_muls(normals[points_count-1], AA_SIZE); | |
8255 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); | |
8256 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); | |
8257 } | |
8258 | |
8259 /* fill elements */ | |
8260 idx1 = index; | |
8261 for (i1 = 0; i1 < count; i1++) { | |
8262 struct nk_vec2 dm; | |
8263 float dmr2; | |
8264 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); | |
8265 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); | |
8266 | |
8267 /* average normals */ | |
8268 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); | |
8269 dmr2 = dm.x * dm.x + dm.y* dm.y; | |
8270 if (dmr2 > 0.000001f) { | |
8271 float scale = 1.0f/dmr2; | |
8272 scale = NK_MIN(100.0f, scale); | |
8273 dm = nk_vec2_muls(dm, scale); | |
8274 } | |
8275 | |
8276 dm = nk_vec2_muls(dm, AA_SIZE); | |
8277 temp[i2*2+0] = nk_vec2_add(points[i2], dm); | |
8278 temp[i2*2+1] = nk_vec2_sub(points[i2], dm); | |
8279 | |
8280 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); | |
8281 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); | |
8282 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); | |
8283 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); | |
8284 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); | |
8285 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); | |
8286 ids += 12; | |
8287 idx1 = idx2; | |
8288 } | |
8289 | |
8290 /* fill vertices */ | |
8291 for (i = 0; i < points_count; ++i) { | |
8292 const struct nk_vec2 uv = list->config.null.uv; | |
8293 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); | |
8294 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); | |
8295 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); | |
8296 } | |
8297 } else { | |
8298 nk_size idx1, i; | |
8299 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; | |
8300 if (!closed) { | |
8301 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); | |
8302 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); | |
8303 | |
8304 temp[0] = nk_vec2_add(points[0], d1); | |
8305 temp[1] = nk_vec2_add(points[0], d2); | |
8306 temp[2] = nk_vec2_sub(points[0], d2); | |
8307 temp[3] = nk_vec2_sub(points[0], d1); | |
8308 | |
8309 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); | |
8310 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); | |
8311 | |
8312 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); | |
8313 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); | |
8314 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); | |
8315 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); | |
8316 } | |
8317 | |
8318 /* add all elements */ | |
8319 idx1 = index; | |
8320 for (i1 = 0; i1 < count; ++i1) { | |
8321 struct nk_vec2 dm_out, dm_in; | |
8322 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); | |
8323 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); | |
8324 | |
8325 /* average normals */ | |
8326 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); | |
8327 float dmr2 = dm.x * dm.x + dm.y* dm.y; | |
8328 if (dmr2 > 0.000001f) { | |
8329 float scale = 1.0f/dmr2; | |
8330 scale = NK_MIN(100.0f, scale); | |
8331 dm = nk_vec2_muls(dm, scale); | |
8332 } | |
8333 | |
8334 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); | |
8335 dm_in = nk_vec2_muls(dm, half_inner_thickness); | |
8336 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); | |
8337 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); | |
8338 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); | |
8339 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); | |
8340 | |
8341 /* add indexes */ | |
8342 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); | |
8343 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); | |
8344 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); | |
8345 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); | |
8346 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); | |
8347 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); | |
8348 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); | |
8349 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); | |
8350 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); | |
8351 ids += 18; | |
8352 idx1 = idx2; | |
8353 } | |
8354 | |
8355 /* add vertices */ | |
8356 for (i = 0; i < points_count; ++i) { | |
8357 const struct nk_vec2 uv = list->config.null.uv; | |
8358 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); | |
8359 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); | |
8360 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); | |
8361 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); | |
8362 } | |
8363 } | |
8364 /* free temporary normals + points */ | |
8365 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); | |
8366 } else { | |
8367 /* NON ANTI-ALIASED STROKE */ | |
8368 nk_size i1 = 0; | |
8369 nk_size idx = list->vertex_count; | |
8370 const nk_size idx_count = count * 6; | |
8371 const nk_size vtx_count = count * 4; | |
8372 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); | |
8373 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); | |
8374 if (!vtx || !ids) return; | |
8375 | |
8376 for (i1 = 0; i1 < count; ++i1) { | |
8377 float dx, dy; | |
8378 const struct nk_vec2 uv = list->config.null.uv; | |
8379 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; | |
8380 const struct nk_vec2 p1 = points[i1]; | |
8381 const struct nk_vec2 p2 = points[i2]; | |
8382 struct nk_vec2 diff = nk_vec2_sub(p2, p1); | |
8383 float len; | |
8384 | |
8385 /* vec2 inverted length */ | |
8386 len = nk_vec2_len_sqr(diff); | |
8387 if (len != 0.0f) | |
8388 len = nk_inv_sqrt(len); | |
8389 else len = 1.0f; | |
8390 diff = nk_vec2_muls(diff, len); | |
8391 | |
8392 /* add vertices */ | |
8393 dx = diff.x * (thickness * 0.5f); | |
8394 dy = diff.y * (thickness * 0.5f); | |
8395 | |
8396 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); | |
8397 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); | |
8398 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); | |
8399 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); | |
8400 | |
8401 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); | |
8402 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); | |
8403 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); | |
8404 | |
8405 ids += 6; | |
8406 idx += 4; | |
8407 } | |
8408 } | |
8409 } | |
8410 | |
8411 NK_API void | |
8412 nk_draw_list_fill_poly_convex(struct nk_draw_list *list, | |
8413 const struct nk_vec2 *points, const unsigned int points_count, | |
8414 struct nk_color color, enum nk_anti_aliasing aliasing) | |
8415 { | |
8416 struct nk_colorf col; | |
8417 struct nk_colorf col_trans; | |
8418 | |
8419 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); | |
8420 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); | |
8421 NK_ASSERT(list); | |
8422 if (!list || points_count < 3) return; | |
8423 | |
8424 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
8425 nk_draw_list_push_userdata(list, list->userdata); | |
8426 #endif | |
8427 | |
8428 color.a = (nk_byte)((float)color.a * list->config.global_alpha); | |
8429 nk_color_fv(&col.r, color); | |
8430 col_trans = col; | |
8431 col_trans.a = 0; | |
8432 | |
8433 if (aliasing == NK_ANTI_ALIASING_ON) { | |
8434 nk_size i = 0; | |
8435 nk_size i0 = 0; | |
8436 nk_size i1 = 0; | |
8437 | |
8438 const float AA_SIZE = 1.0f; | |
8439 nk_size vertex_offset = 0; | |
8440 nk_size index = list->vertex_count; | |
8441 | |
8442 const nk_size idx_count = (points_count-2)*3 + points_count*6; | |
8443 const nk_size vtx_count = (points_count*2); | |
8444 | |
8445 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); | |
8446 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); | |
8447 | |
8448 nk_size size = 0; | |
8449 struct nk_vec2 *normals = 0; | |
8450 unsigned int vtx_inner_idx = (unsigned int)(index + 0); | |
8451 unsigned int vtx_outer_idx = (unsigned int)(index + 1); | |
8452 if (!vtx || !ids) return; | |
8453 | |
8454 /* temporary allocate normals */ | |
8455 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); | |
8456 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); | |
8457 size = pnt_size * points_count; | |
8458 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); | |
8459 NK_ASSERT(normals); | |
8460 if (!normals) return; | |
8461 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); | |
8462 | |
8463 /* add elements */ | |
8464 for (i = 2; i < points_count; i++) { | |
8465 ids[0] = (nk_draw_index)(vtx_inner_idx); | |
8466 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); | |
8467 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); | |
8468 ids += 3; | |
8469 } | |
8470 | |
8471 /* compute normals */ | |
8472 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { | |
8473 struct nk_vec2 p0 = points[i0]; | |
8474 struct nk_vec2 p1 = points[i1]; | |
8475 struct nk_vec2 diff = nk_vec2_sub(p1, p0); | |
8476 | |
8477 /* vec2 inverted length */ | |
8478 float len = nk_vec2_len_sqr(diff); | |
8479 if (len != 0.0f) | |
8480 len = nk_inv_sqrt(len); | |
8481 else len = 1.0f; | |
8482 diff = nk_vec2_muls(diff, len); | |
8483 | |
8484 normals[i0].x = diff.y; | |
8485 normals[i0].y = -diff.x; | |
8486 } | |
8487 | |
8488 /* add vertices + indexes */ | |
8489 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { | |
8490 const struct nk_vec2 uv = list->config.null.uv; | |
8491 struct nk_vec2 n0 = normals[i0]; | |
8492 struct nk_vec2 n1 = normals[i1]; | |
8493 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); | |
8494 float dmr2 = dm.x*dm.x + dm.y*dm.y; | |
8495 if (dmr2 > 0.000001f) { | |
8496 float scale = 1.0f / dmr2; | |
8497 scale = NK_MIN(scale, 100.0f); | |
8498 dm = nk_vec2_muls(dm, scale); | |
8499 } | |
8500 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); | |
8501 | |
8502 /* add vertices */ | |
8503 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); | |
8504 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); | |
8505 | |
8506 /* add indexes */ | |
8507 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); | |
8508 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); | |
8509 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); | |
8510 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); | |
8511 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); | |
8512 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); | |
8513 ids += 6; | |
8514 } | |
8515 /* free temporary normals + points */ | |
8516 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); | |
8517 } else { | |
8518 nk_size i = 0; | |
8519 nk_size index = list->vertex_count; | |
8520 const nk_size idx_count = (points_count-2)*3; | |
8521 const nk_size vtx_count = points_count; | |
8522 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); | |
8523 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); | |
8524 | |
8525 if (!vtx || !ids) return; | |
8526 for (i = 0; i < vtx_count; ++i) | |
8527 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); | |
8528 for (i = 2; i < points_count; ++i) { | |
8529 ids[0] = (nk_draw_index)index; | |
8530 ids[1] = (nk_draw_index)(index+ i - 1); | |
8531 ids[2] = (nk_draw_index)(index+i); | |
8532 ids += 3; | |
8533 } | |
8534 } | |
8535 } | |
8536 | |
8537 NK_API void | |
8538 nk_draw_list_path_clear(struct nk_draw_list *list) | |
8539 { | |
8540 NK_ASSERT(list); | |
8541 if (!list) return; | |
8542 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); | |
8543 list->path_count = 0; | |
8544 list->path_offset = 0; | |
8545 } | |
8546 | |
8547 NK_API void | |
8548 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) | |
8549 { | |
8550 struct nk_vec2 *points = 0; | |
8551 struct nk_draw_command *cmd = 0; | |
8552 NK_ASSERT(list); | |
8553 if (!list) return; | |
8554 if (!list->cmd_count) | |
8555 nk_draw_list_add_clip(list, nk_null_rect); | |
8556 | |
8557 cmd = nk_draw_list_command_last(list); | |
8558 if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) | |
8559 nk_draw_list_push_image(list, list->config.null.texture); | |
8560 | |
8561 points = nk_draw_list_alloc_path(list, 1); | |
8562 if (!points) return; | |
8563 points[0] = pos; | |
8564 } | |
8565 | |
8566 NK_API void | |
8567 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, | |
8568 float radius, int a_min, int a_max) | |
8569 { | |
8570 int a = 0; | |
8571 NK_ASSERT(list); | |
8572 if (!list) return; | |
8573 if (a_min <= a_max) { | |
8574 for (a = a_min; a <= a_max; a++) { | |
8575 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; | |
8576 const float x = center.x + c.x * radius; | |
8577 const float y = center.y + c.y * radius; | |
8578 nk_draw_list_path_line_to(list, nk_vec2(x, y)); | |
8579 } | |
8580 } | |
8581 } | |
8582 | |
8583 NK_API void | |
8584 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, | |
8585 float radius, float a_min, float a_max, unsigned int segments) | |
8586 { | |
8587 unsigned int i = 0; | |
8588 NK_ASSERT(list); | |
8589 if (!list) return; | |
8590 if (radius == 0.0f) return; | |
8591 | |
8592 /* This algorithm for arc drawing relies on these two trigonometric identities[1]: | |
8593 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) | |
8594 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) | |
8595 | |
8596 Two coordinates (x, y) of a point on a circle centered on | |
8597 the origin can be written in polar form as: | |
8598 x = r * cos(a) | |
8599 y = r * sin(a) | |
8600 where r is the radius of the circle, | |
8601 a is the angle between (x, y) and the origin. | |
8602 | |
8603 This allows us to rotate the coordinates around the | |
8604 origin by an angle b using the following transformation: | |
8605 x' = r * cos(a + b) = x * cos(b) - y * sin(b) | |
8606 y' = r * sin(a + b) = y * cos(b) + x * sin(b) | |
8607 | |
8608 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities | |
8609 */ | |
8610 const float d_angle = (a_max - a_min) / (float)segments; | |
8611 const float sin_d = (float)NK_SIN(d_angle); | |
8612 const float cos_d = (float)NK_COS(d_angle); | |
8613 | |
8614 float cx = (float)NK_COS(a_min) * radius; | |
8615 float cy = (float)NK_SIN(a_min) * radius; | |
8616 for(i = 0; i <= segments; ++i) { | |
8617 const float x = center.x + cx; | |
8618 const float y = center.y + cy; | |
8619 nk_draw_list_path_line_to(list, nk_vec2(x, y)); | |
8620 | |
8621 const float new_cx = cx * cos_d - cy * sin_d; | |
8622 const float new_cy = cy * cos_d + cx * sin_d; | |
8623 cx = new_cx; | |
8624 cy = new_cy; | |
8625 } | |
8626 } | |
8627 | |
8628 NK_API void | |
8629 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, | |
8630 struct nk_vec2 b, float rounding) | |
8631 { | |
8632 float r; | |
8633 NK_ASSERT(list); | |
8634 if (!list) return; | |
8635 r = rounding; | |
8636 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); | |
8637 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); | |
8638 | |
8639 if (r == 0.0f) { | |
8640 nk_draw_list_path_line_to(list, a); | |
8641 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); | |
8642 nk_draw_list_path_line_to(list, b); | |
8643 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); | |
8644 } else { | |
8645 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); | |
8646 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); | |
8647 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); | |
8648 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); | |
8649 } | |
8650 } | |
8651 | |
8652 NK_API void | |
8653 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, | |
8654 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) | |
8655 { | |
8656 float t_step; | |
8657 unsigned int i_step; | |
8658 struct nk_vec2 p1; | |
8659 | |
8660 NK_ASSERT(list); | |
8661 NK_ASSERT(list->path_count); | |
8662 if (!list || !list->path_count) return; | |
8663 num_segments = NK_MAX(num_segments, 1); | |
8664 | |
8665 p1 = nk_draw_list_path_last(list); | |
8666 t_step = 1.0f/(float)num_segments; | |
8667 for (i_step = 1; i_step <= num_segments; ++i_step) { | |
8668 float t = t_step * (float)i_step; | |
8669 float u = 1.0f - t; | |
8670 float w1 = u*u*u; | |
8671 float w2 = 3*u*u*t; | |
8672 float w3 = 3*u*t*t; | |
8673 float w4 = t * t *t; | |
8674 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; | |
8675 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; | |
8676 nk_draw_list_path_line_to(list, nk_vec2(x,y)); | |
8677 } | |
8678 } | |
8679 | |
8680 NK_API void | |
8681 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) | |
8682 { | |
8683 struct nk_vec2 *points; | |
8684 NK_ASSERT(list); | |
8685 if (!list) return; | |
8686 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); | |
8687 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); | |
8688 nk_draw_list_path_clear(list); | |
8689 } | |
8690 | |
8691 NK_API void | |
8692 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, | |
8693 enum nk_draw_list_stroke closed, float thickness) | |
8694 { | |
8695 struct nk_vec2 *points; | |
8696 NK_ASSERT(list); | |
8697 if (!list) return; | |
8698 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); | |
8699 nk_draw_list_stroke_poly_line(list, points, list->path_count, color, | |
8700 closed, thickness, list->config.line_AA); | |
8701 nk_draw_list_path_clear(list); | |
8702 } | |
8703 | |
8704 NK_API void | |
8705 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, | |
8706 struct nk_vec2 b, struct nk_color col, float thickness) | |
8707 { | |
8708 NK_ASSERT(list); | |
8709 if (!list || !col.a) return; | |
8710 if (list->line_AA == NK_ANTI_ALIASING_ON) { | |
8711 nk_draw_list_path_line_to(list, a); | |
8712 nk_draw_list_path_line_to(list, b); | |
8713 } else { | |
8714 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f))); | |
8715 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f))); | |
8716 } | |
8717 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); | |
8718 } | |
8719 | |
8720 NK_API void | |
8721 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, | |
8722 struct nk_color col, float rounding) | |
8723 { | |
8724 NK_ASSERT(list); | |
8725 if (!list || !col.a) return; | |
8726 | |
8727 if (list->line_AA == NK_ANTI_ALIASING_ON) { | |
8728 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), | |
8729 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); | |
8730 } else { | |
8731 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), | |
8732 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); | |
8733 } nk_draw_list_path_fill(list, col); | |
8734 } | |
8735 | |
8736 NK_API void | |
8737 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, | |
8738 struct nk_color col, float rounding, float thickness) | |
8739 { | |
8740 NK_ASSERT(list); | |
8741 if (!list || !col.a) return; | |
8742 if (list->line_AA == NK_ANTI_ALIASING_ON) { | |
8743 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), | |
8744 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); | |
8745 } else { | |
8746 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), | |
8747 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); | |
8748 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); | |
8749 } | |
8750 | |
8751 NK_API void | |
8752 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, | |
8753 struct nk_color left, struct nk_color top, struct nk_color right, | |
8754 struct nk_color bottom) | |
8755 { | |
8756 void *vtx; | |
8757 struct nk_colorf col_left, col_top; | |
8758 struct nk_colorf col_right, col_bottom; | |
8759 nk_draw_index *idx; | |
8760 nk_draw_index index; | |
8761 | |
8762 nk_color_fv(&col_left.r, left); | |
8763 nk_color_fv(&col_right.r, right); | |
8764 nk_color_fv(&col_top.r, top); | |
8765 nk_color_fv(&col_bottom.r, bottom); | |
8766 | |
8767 NK_ASSERT(list); | |
8768 if (!list) return; | |
8769 | |
8770 nk_draw_list_push_image(list, list->config.null.texture); | |
8771 index = (nk_draw_index)list->vertex_count; | |
8772 vtx = nk_draw_list_alloc_vertices(list, 4); | |
8773 idx = nk_draw_list_alloc_elements(list, 6); | |
8774 if (!vtx || !idx) return; | |
8775 | |
8776 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); | |
8777 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); | |
8778 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); | |
8779 | |
8780 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); | |
8781 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); | |
8782 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); | |
8783 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); | |
8784 } | |
8785 | |
8786 NK_API void | |
8787 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, | |
8788 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) | |
8789 { | |
8790 NK_ASSERT(list); | |
8791 if (!list || !col.a) return; | |
8792 nk_draw_list_path_line_to(list, a); | |
8793 nk_draw_list_path_line_to(list, b); | |
8794 nk_draw_list_path_line_to(list, c); | |
8795 nk_draw_list_path_fill(list, col); | |
8796 } | |
8797 | |
8798 NK_API void | |
8799 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, | |
8800 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) | |
8801 { | |
8802 NK_ASSERT(list); | |
8803 if (!list || !col.a) return; | |
8804 nk_draw_list_path_line_to(list, a); | |
8805 nk_draw_list_path_line_to(list, b); | |
8806 nk_draw_list_path_line_to(list, c); | |
8807 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); | |
8808 } | |
8809 | |
8810 NK_API void | |
8811 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, | |
8812 float radius, struct nk_color col, unsigned int segs) | |
8813 { | |
8814 float a_max; | |
8815 NK_ASSERT(list); | |
8816 if (!list || !col.a) return; | |
8817 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; | |
8818 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); | |
8819 nk_draw_list_path_fill(list, col); | |
8820 } | |
8821 | |
8822 NK_API void | |
8823 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, | |
8824 float radius, struct nk_color col, unsigned int segs, float thickness) | |
8825 { | |
8826 float a_max; | |
8827 NK_ASSERT(list); | |
8828 if (!list || !col.a) return; | |
8829 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; | |
8830 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); | |
8831 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); | |
8832 } | |
8833 | |
8834 NK_API void | |
8835 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, | |
8836 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, | |
8837 struct nk_color col, unsigned int segments, float thickness) | |
8838 { | |
8839 NK_ASSERT(list); | |
8840 if (!list || !col.a) return; | |
8841 nk_draw_list_path_line_to(list, p0); | |
8842 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); | |
8843 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); | |
8844 } | |
8845 | |
8846 NK_INTERN void | |
8847 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, | |
8848 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, | |
8849 struct nk_color color) | |
8850 { | |
8851 void *vtx; | |
8852 struct nk_vec2 uvb; | |
8853 struct nk_vec2 uvd; | |
8854 struct nk_vec2 b; | |
8855 struct nk_vec2 d; | |
8856 | |
8857 struct nk_colorf col; | |
8858 nk_draw_index *idx; | |
8859 nk_draw_index index; | |
8860 NK_ASSERT(list); | |
8861 if (!list) return; | |
8862 | |
8863 nk_color_fv(&col.r, color); | |
8864 uvb = nk_vec2(uvc.x, uva.y); | |
8865 uvd = nk_vec2(uva.x, uvc.y); | |
8866 b = nk_vec2(c.x, a.y); | |
8867 d = nk_vec2(a.x, c.y); | |
8868 | |
8869 index = (nk_draw_index)list->vertex_count; | |
8870 vtx = nk_draw_list_alloc_vertices(list, 4); | |
8871 idx = nk_draw_list_alloc_elements(list, 6); | |
8872 if (!vtx || !idx) return; | |
8873 | |
8874 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); | |
8875 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); | |
8876 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); | |
8877 | |
8878 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); | |
8879 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); | |
8880 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); | |
8881 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); | |
8882 } | |
8883 | |
8884 NK_API void | |
8885 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, | |
8886 struct nk_rect rect, struct nk_color color) | |
8887 { | |
8888 NK_ASSERT(list); | |
8889 if (!list) return; | |
8890 /* push new command with given texture */ | |
8891 nk_draw_list_push_image(list, texture.handle); | |
8892 if (nk_image_is_subimage(&texture)) { | |
8893 /* add region inside of the texture */ | |
8894 struct nk_vec2 uv[2]; | |
8895 uv[0].x = (float)texture.region[0]/(float)texture.w; | |
8896 uv[0].y = (float)texture.region[1]/(float)texture.h; | |
8897 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; | |
8898 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; | |
8899 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), | |
8900 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); | |
8901 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), | |
8902 nk_vec2(rect.x + rect.w, rect.y + rect.h), | |
8903 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); | |
8904 } | |
8905 | |
8906 NK_API void | |
8907 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, | |
8908 struct nk_rect rect, const char *text, int len, float font_height, | |
8909 struct nk_color fg) | |
8910 { | |
8911 float x = 0; | |
8912 int text_len = 0; | |
8913 nk_rune unicode = 0; | |
8914 nk_rune next = 0; | |
8915 int glyph_len = 0; | |
8916 int next_glyph_len = 0; | |
8917 struct nk_user_font_glyph g; | |
8918 | |
8919 NK_ASSERT(list); | |
8920 if (!list || !len || !text) return; | |
8921 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, | |
8922 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; | |
8923 | |
8924 nk_draw_list_push_image(list, font->texture); | |
8925 x = rect.x; | |
8926 glyph_len = nk_utf_decode(text, &unicode, len); | |
8927 if (!glyph_len) return; | |
8928 | |
8929 /* draw every glyph image */ | |
8930 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); | |
8931 while (text_len < len && glyph_len) { | |
8932 float gx, gy, gh, gw; | |
8933 float char_width = 0; | |
8934 if (unicode == NK_UTF_INVALID) break; | |
8935 | |
8936 /* query currently drawn glyph information */ | |
8937 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); | |
8938 font->query(font->userdata, font_height, &g, unicode, | |
8939 (next == NK_UTF_INVALID) ? '\0' : next); | |
8940 | |
8941 /* calculate and draw glyph drawing rectangle and image */ | |
8942 gx = x + g.offset.x; | |
8943 gy = rect.y + g.offset.y; | |
8944 gw = g.width; gh = g.height; | |
8945 char_width = g.xadvance; | |
8946 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), | |
8947 g.uv[0], g.uv[1], fg); | |
8948 | |
8949 /* offset next glyph */ | |
8950 text_len += glyph_len; | |
8951 x += char_width; | |
8952 glyph_len = next_glyph_len; | |
8953 unicode = next; | |
8954 } | |
8955 } | |
8956 | |
8957 NK_API nk_flags | |
8958 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, | |
8959 struct nk_buffer *vertices, struct nk_buffer *elements, | |
8960 const struct nk_convert_config *config) | |
8961 { | |
8962 nk_flags res = NK_CONVERT_SUCCESS; | |
8963 const struct nk_command *cmd; | |
8964 NK_ASSERT(ctx); | |
8965 NK_ASSERT(cmds); | |
8966 NK_ASSERT(vertices); | |
8967 NK_ASSERT(elements); | |
8968 NK_ASSERT(config); | |
8969 NK_ASSERT(config->vertex_layout); | |
8970 NK_ASSERT(config->vertex_size); | |
8971 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) | |
8972 return NK_CONVERT_INVALID_PARAM; | |
8973 | |
8974 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements, | |
8975 config->line_AA, config->shape_AA); | |
8976 nk_foreach(cmd, ctx) | |
8977 { | |
8978 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
8979 ctx->draw_list.userdata = cmd->userdata; | |
8980 #endif | |
8981 switch (cmd->type) { | |
8982 case NK_COMMAND_NOP: break; | |
8983 case NK_COMMAND_SCISSOR: { | |
8984 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; | |
8985 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); | |
8986 } break; | |
8987 case NK_COMMAND_LINE: { | |
8988 const struct nk_command_line *l = (const struct nk_command_line*)cmd; | |
8989 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), | |
8990 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); | |
8991 } break; | |
8992 case NK_COMMAND_CURVE: { | |
8993 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; | |
8994 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), | |
8995 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, | |
8996 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, | |
8997 config->curve_segment_count, q->line_thickness); | |
8998 } break; | |
8999 case NK_COMMAND_RECT: { | |
9000 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; | |
9001 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), | |
9002 r->color, (float)r->rounding, r->line_thickness); | |
9003 } break; | |
9004 case NK_COMMAND_RECT_FILLED: { | |
9005 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; | |
9006 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), | |
9007 r->color, (float)r->rounding); | |
9008 } break; | |
9009 case NK_COMMAND_RECT_MULTI_COLOR: { | |
9010 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; | |
9011 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), | |
9012 r->left, r->top, r->right, r->bottom); | |
9013 } break; | |
9014 case NK_COMMAND_CIRCLE: { | |
9015 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; | |
9016 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, | |
9017 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, | |
9018 config->circle_segment_count, c->line_thickness); | |
9019 } break; | |
9020 case NK_COMMAND_CIRCLE_FILLED: { | |
9021 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; | |
9022 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, | |
9023 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, | |
9024 config->circle_segment_count); | |
9025 } break; | |
9026 case NK_COMMAND_ARC: { | |
9027 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; | |
9028 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); | |
9029 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, | |
9030 c->a[0], c->a[1], config->arc_segment_count); | |
9031 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); | |
9032 } break; | |
9033 case NK_COMMAND_ARC_FILLED: { | |
9034 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; | |
9035 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); | |
9036 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, | |
9037 c->a[0], c->a[1], config->arc_segment_count); | |
9038 nk_draw_list_path_fill(&ctx->draw_list, c->color); | |
9039 } break; | |
9040 case NK_COMMAND_TRIANGLE: { | |
9041 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; | |
9042 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), | |
9043 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, | |
9044 t->line_thickness); | |
9045 } break; | |
9046 case NK_COMMAND_TRIANGLE_FILLED: { | |
9047 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; | |
9048 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), | |
9049 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); | |
9050 } break; | |
9051 case NK_COMMAND_POLYGON: { | |
9052 int i; | |
9053 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; | |
9054 for (i = 0; i < p->point_count; ++i) { | |
9055 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); | |
9056 nk_draw_list_path_line_to(&ctx->draw_list, pnt); | |
9057 } | |
9058 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); | |
9059 } break; | |
9060 case NK_COMMAND_POLYGON_FILLED: { | |
9061 int i; | |
9062 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; | |
9063 for (i = 0; i < p->point_count; ++i) { | |
9064 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); | |
9065 nk_draw_list_path_line_to(&ctx->draw_list, pnt); | |
9066 } | |
9067 nk_draw_list_path_fill(&ctx->draw_list, p->color); | |
9068 } break; | |
9069 case NK_COMMAND_POLYLINE: { | |
9070 int i; | |
9071 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; | |
9072 for (i = 0; i < p->point_count; ++i) { | |
9073 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); | |
9074 nk_draw_list_path_line_to(&ctx->draw_list, pnt); | |
9075 } | |
9076 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); | |
9077 } break; | |
9078 case NK_COMMAND_TEXT: { | |
9079 const struct nk_command_text *t = (const struct nk_command_text*)cmd; | |
9080 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), | |
9081 t->string, t->length, t->height, t->foreground); | |
9082 } break; | |
9083 case NK_COMMAND_IMAGE: { | |
9084 const struct nk_command_image *i = (const struct nk_command_image*)cmd; | |
9085 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); | |
9086 } break; | |
9087 case NK_COMMAND_CUSTOM: { | |
9088 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd; | |
9089 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data); | |
9090 } break; | |
9091 default: break; | |
9092 } | |
9093 } | |
9094 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0; | |
9095 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0; | |
9096 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0; | |
9097 return res; | |
9098 } | |
9099 NK_API const struct nk_draw_command* | |
9100 nk__draw_begin(const struct nk_context *ctx, | |
9101 const struct nk_buffer *buffer) | |
9102 {return nk__draw_list_begin(&ctx->draw_list, buffer);} | |
9103 | |
9104 NK_API const struct nk_draw_command* | |
9105 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) | |
9106 {return nk__draw_list_end(&ctx->draw_list, buffer);} | |
9107 | |
9108 NK_API const struct nk_draw_command* | |
9109 nk__draw_next(const struct nk_draw_command *cmd, | |
9110 const struct nk_buffer *buffer, const struct nk_context *ctx) | |
9111 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);} | |
9112 | |
9113 #endif | |
9114 | |
9115 /* | |
9116 * ============================================================== | |
9117 * | |
9118 * FONT HANDLING | |
9119 * | |
9120 * =============================================================== | |
9121 */ | |
9122 #ifdef NK_INCLUDE_FONT_BAKING | |
9123 /* ------------------------------------------------------------- | |
9124 * | |
9125 * RECT PACK | |
9126 * | |
9127 * --------------------------------------------------------------*/ | |
9128 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */ | |
9129 /* Sean Barrett 2014 */ | |
9130 #define NK_RP__MAXVAL 0xffff | |
9131 typedef unsigned short nk_rp_coord; | |
9132 | |
9133 struct nk_rp_rect { | |
9134 /* reserved for your use: */ | |
9135 int id; | |
9136 /* input: */ | |
9137 nk_rp_coord w, h; | |
9138 /* output: */ | |
9139 nk_rp_coord x, y; | |
9140 int was_packed; | |
9141 /* non-zero if valid packing */ | |
9142 }; /* 16 bytes, nominally */ | |
9143 | |
9144 struct nk_rp_node { | |
9145 nk_rp_coord x,y; | |
9146 struct nk_rp_node *next; | |
9147 }; | |
9148 | |
9149 struct nk_rp_context { | |
9150 int width; | |
9151 int height; | |
9152 int align; | |
9153 int init_mode; | |
9154 int heuristic; | |
9155 int num_nodes; | |
9156 struct nk_rp_node *active_head; | |
9157 struct nk_rp_node *free_head; | |
9158 struct nk_rp_node extra[2]; | |
9159 /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ | |
9160 }; | |
9161 | |
9162 struct nk_rp__findresult { | |
9163 int x,y; | |
9164 struct nk_rp_node **prev_link; | |
9165 }; | |
9166 | |
9167 enum NK_RP_HEURISTIC { | |
9168 NK_RP_HEURISTIC_Skyline_default=0, | |
9169 NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default, | |
9170 NK_RP_HEURISTIC_Skyline_BF_sortHeight | |
9171 }; | |
9172 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1}; | |
9173 | |
9174 NK_INTERN void | |
9175 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem) | |
9176 { | |
9177 if (allow_out_of_mem) | |
9178 /* if it's ok to run out of memory, then don't bother aligning them; */ | |
9179 /* this gives better packing, but may fail due to OOM (even though */ | |
9180 /* the rectangles easily fit). @TODO a smarter approach would be to only */ | |
9181 /* quantize once we've hit OOM, then we could get rid of this parameter. */ | |
9182 context->align = 1; | |
9183 else { | |
9184 /* if it's not ok to run out of memory, then quantize the widths */ | |
9185 /* so that num_nodes is always enough nodes. */ | |
9186 /* */ | |
9187 /* I.e. num_nodes * align >= width */ | |
9188 /* align >= width / num_nodes */ | |
9189 /* align = ceil(width/num_nodes) */ | |
9190 context->align = (context->width + context->num_nodes-1) / context->num_nodes; | |
9191 } | |
9192 } | |
9193 | |
9194 NK_INTERN void | |
9195 nk_rp_init_target(struct nk_rp_context *context, int width, int height, | |
9196 struct nk_rp_node *nodes, int num_nodes) | |
9197 { | |
9198 int i; | |
9199 #ifndef STBRP_LARGE_RECTS | |
9200 NK_ASSERT(width <= 0xffff && height <= 0xffff); | |
9201 #endif | |
9202 | |
9203 for (i=0; i < num_nodes-1; ++i) | |
9204 nodes[i].next = &nodes[i+1]; | |
9205 nodes[i].next = 0; | |
9206 context->init_mode = NK_RP__INIT_skyline; | |
9207 context->heuristic = NK_RP_HEURISTIC_Skyline_default; | |
9208 context->free_head = &nodes[0]; | |
9209 context->active_head = &context->extra[0]; | |
9210 context->width = width; | |
9211 context->height = height; | |
9212 context->num_nodes = num_nodes; | |
9213 nk_rp_setup_allow_out_of_mem(context, 0); | |
9214 | |
9215 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ | |
9216 context->extra[0].x = 0; | |
9217 context->extra[0].y = 0; | |
9218 context->extra[0].next = &context->extra[1]; | |
9219 context->extra[1].x = (nk_rp_coord) width; | |
9220 context->extra[1].y = 65535; | |
9221 context->extra[1].next = 0; | |
9222 } | |
9223 | |
9224 /* find minimum y position if it starts at x1 */ | |
9225 NK_INTERN int | |
9226 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first, | |
9227 int x0, int width, int *pwaste) | |
9228 { | |
9229 struct nk_rp_node *node = first; | |
9230 int x1 = x0 + width; | |
9231 int min_y, visited_width, waste_area; | |
9232 NK_ASSERT(first->x <= x0); | |
9233 NK_UNUSED(c); | |
9234 | |
9235 NK_ASSERT(node->next->x > x0); | |
9236 /* we ended up handling this in the caller for efficiency */ | |
9237 NK_ASSERT(node->x <= x0); | |
9238 | |
9239 min_y = 0; | |
9240 waste_area = 0; | |
9241 visited_width = 0; | |
9242 while (node->x < x1) | |
9243 { | |
9244 if (node->y > min_y) { | |
9245 /* raise min_y higher. */ | |
9246 /* we've accounted for all waste up to min_y, */ | |
9247 /* but we'll now add more waste for everything we've visited */ | |
9248 waste_area += visited_width * (node->y - min_y); | |
9249 min_y = node->y; | |
9250 /* the first time through, visited_width might be reduced */ | |
9251 if (node->x < x0) | |
9252 visited_width += node->next->x - x0; | |
9253 else | |
9254 visited_width += node->next->x - node->x; | |
9255 } else { | |
9256 /* add waste area */ | |
9257 int under_width = node->next->x - node->x; | |
9258 if (under_width + visited_width > width) | |
9259 under_width = width - visited_width; | |
9260 waste_area += under_width * (min_y - node->y); | |
9261 visited_width += under_width; | |
9262 } | |
9263 node = node->next; | |
9264 } | |
9265 *pwaste = waste_area; | |
9266 return min_y; | |
9267 } | |
9268 | |
9269 NK_INTERN struct nk_rp__findresult | |
9270 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height) | |
9271 { | |
9272 int best_waste = (1<<30), best_x, best_y = (1 << 30); | |
9273 struct nk_rp__findresult fr; | |
9274 struct nk_rp_node **prev, *node, *tail, **best = 0; | |
9275 | |
9276 /* align to multiple of c->align */ | |
9277 width = (width + c->align - 1); | |
9278 width -= width % c->align; | |
9279 NK_ASSERT(width % c->align == 0); | |
9280 | |
9281 node = c->active_head; | |
9282 prev = &c->active_head; | |
9283 while (node->x + width <= c->width) { | |
9284 int y,waste; | |
9285 y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste); | |
9286 /* actually just want to test BL */ | |
9287 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) { | |
9288 /* bottom left */ | |
9289 if (y < best_y) { | |
9290 best_y = y; | |
9291 best = prev; | |
9292 } | |
9293 } else { | |
9294 /* best-fit */ | |
9295 if (y + height <= c->height) { | |
9296 /* can only use it if it first vertically */ | |
9297 if (y < best_y || (y == best_y && waste < best_waste)) { | |
9298 best_y = y; | |
9299 best_waste = waste; | |
9300 best = prev; | |
9301 } | |
9302 } | |
9303 } | |
9304 prev = &node->next; | |
9305 node = node->next; | |
9306 } | |
9307 best_x = (best == 0) ? 0 : (*best)->x; | |
9308 | |
9309 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ | |
9310 /* */ | |
9311 /* e.g, if fitting */ | |
9312 /* */ | |
9313 /* ____________________ */ | |
9314 /* |____________________| */ | |
9315 /* */ | |
9316 /* into */ | |
9317 /* */ | |
9318 /* | | */ | |
9319 /* | ____________| */ | |
9320 /* |____________| */ | |
9321 /* */ | |
9322 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ | |
9323 /* */ | |
9324 /* This makes BF take about 2x the time */ | |
9325 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight) | |
9326 { | |
9327 tail = c->active_head; | |
9328 node = c->active_head; | |
9329 prev = &c->active_head; | |
9330 /* find first node that's admissible */ | |
9331 while (tail->x < width) | |
9332 tail = tail->next; | |
9333 while (tail) | |
9334 { | |
9335 int xpos = tail->x - width; | |
9336 int y,waste; | |
9337 NK_ASSERT(xpos >= 0); | |
9338 /* find the left position that matches this */ | |
9339 while (node->next->x <= xpos) { | |
9340 prev = &node->next; | |
9341 node = node->next; | |
9342 } | |
9343 NK_ASSERT(node->next->x > xpos && node->x <= xpos); | |
9344 y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste); | |
9345 if (y + height < c->height) { | |
9346 if (y <= best_y) { | |
9347 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { | |
9348 best_x = xpos; | |
9349 NK_ASSERT(y <= best_y); | |
9350 best_y = y; | |
9351 best_waste = waste; | |
9352 best = prev; | |
9353 } | |
9354 } | |
9355 } | |
9356 tail = tail->next; | |
9357 } | |
9358 } | |
9359 fr.prev_link = best; | |
9360 fr.x = best_x; | |
9361 fr.y = best_y; | |
9362 return fr; | |
9363 } | |
9364 | |
9365 NK_INTERN struct nk_rp__findresult | |
9366 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height) | |
9367 { | |
9368 /* find best position according to heuristic */ | |
9369 struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height); | |
9370 struct nk_rp_node *node, *cur; | |
9371 | |
9372 /* bail if: */ | |
9373 /* 1. it failed */ | |
9374 /* 2. the best node doesn't fit (we don't always check this) */ | |
9375 /* 3. we're out of memory */ | |
9376 if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) { | |
9377 res.prev_link = 0; | |
9378 return res; | |
9379 } | |
9380 | |
9381 /* on success, create new node */ | |
9382 node = context->free_head; | |
9383 node->x = (nk_rp_coord) res.x; | |
9384 node->y = (nk_rp_coord) (res.y + height); | |
9385 | |
9386 context->free_head = node->next; | |
9387 | |
9388 /* insert the new node into the right starting point, and */ | |
9389 /* let 'cur' point to the remaining nodes needing to be */ | |
9390 /* stitched back in */ | |
9391 cur = *res.prev_link; | |
9392 if (cur->x < res.x) { | |
9393 /* preserve the existing one, so start testing with the next one */ | |
9394 struct nk_rp_node *next = cur->next; | |
9395 cur->next = node; | |
9396 cur = next; | |
9397 } else { | |
9398 *res.prev_link = node; | |
9399 } | |
9400 | |
9401 /* from here, traverse cur and free the nodes, until we get to one */ | |
9402 /* that shouldn't be freed */ | |
9403 while (cur->next && cur->next->x <= res.x + width) { | |
9404 struct nk_rp_node *next = cur->next; | |
9405 /* move the current node to the free list */ | |
9406 cur->next = context->free_head; | |
9407 context->free_head = cur; | |
9408 cur = next; | |
9409 } | |
9410 /* stitch the list back in */ | |
9411 node->next = cur; | |
9412 | |
9413 if (cur->x < res.x + width) | |
9414 cur->x = (nk_rp_coord) (res.x + width); | |
9415 return res; | |
9416 } | |
9417 | |
9418 NK_INTERN int | |
9419 nk_rect_height_compare(const void *a, const void *b) | |
9420 { | |
9421 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; | |
9422 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; | |
9423 if (p->h > q->h) | |
9424 return -1; | |
9425 if (p->h < q->h) | |
9426 return 1; | |
9427 return (p->w > q->w) ? -1 : (p->w < q->w); | |
9428 } | |
9429 | |
9430 NK_INTERN int | |
9431 nk_rect_original_order(const void *a, const void *b) | |
9432 { | |
9433 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; | |
9434 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; | |
9435 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); | |
9436 } | |
9437 | |
9438 NK_INTERN void | |
9439 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*)) | |
9440 { | |
9441 /* iterative quick sort */ | |
9442 #define NK_MAX_SORT_STACK 64 | |
9443 unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0; | |
9444 unsigned seed = len/2 * 69069+1; | |
9445 for (;;) { | |
9446 for (; left+1 < len; len++) { | |
9447 struct nk_rp_rect pivot, tmp; | |
9448 if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0]; | |
9449 pivot = array[left+seed%(len-left)]; | |
9450 seed = seed * 69069 + 1; | |
9451 stack[pos++] = len; | |
9452 for (right = left-1;;) { | |
9453 while (cmp(&array[++right], &pivot) < 0); | |
9454 while (cmp(&pivot, &array[--len]) < 0); | |
9455 if (right >= len) break; | |
9456 tmp = array[right]; | |
9457 array[right] = array[len]; | |
9458 array[len] = tmp; | |
9459 } | |
9460 } | |
9461 if (pos == 0) break; | |
9462 left = len; | |
9463 len = stack[--pos]; | |
9464 } | |
9465 #undef NK_MAX_SORT_STACK | |
9466 } | |
9467 | |
9468 NK_INTERN void | |
9469 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects) | |
9470 { | |
9471 int i; | |
9472 /* we use the 'was_packed' field internally to allow sorting/unsorting */ | |
9473 for (i=0; i < num_rects; ++i) { | |
9474 rects[i].was_packed = i; | |
9475 } | |
9476 | |
9477 /* sort according to heuristic */ | |
9478 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare); | |
9479 | |
9480 for (i=0; i < num_rects; ++i) { | |
9481 struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); | |
9482 if (fr.prev_link) { | |
9483 rects[i].x = (nk_rp_coord) fr.x; | |
9484 rects[i].y = (nk_rp_coord) fr.y; | |
9485 } else { | |
9486 rects[i].x = rects[i].y = NK_RP__MAXVAL; | |
9487 } | |
9488 } | |
9489 | |
9490 /* unsort */ | |
9491 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order); | |
9492 | |
9493 /* set was_packed flags */ | |
9494 for (i=0; i < num_rects; ++i) | |
9495 rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL); | |
9496 } | |
9497 | |
9498 /* | |
9499 * ============================================================== | |
9500 * | |
9501 * TRUETYPE | |
9502 * | |
9503 * =============================================================== | |
9504 */ | |
9505 /* stb_truetype.h - v1.07 - public domain */ | |
9506 #define NK_TT_MAX_OVERSAMPLE 8 | |
9507 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1) | |
9508 | |
9509 struct nk_tt_bakedchar { | |
9510 unsigned short x0,y0,x1,y1; | |
9511 /* coordinates of bbox in bitmap */ | |
9512 float xoff,yoff,xadvance; | |
9513 }; | |
9514 | |
9515 struct nk_tt_aligned_quad{ | |
9516 float x0,y0,s0,t0; /* top-left */ | |
9517 float x1,y1,s1,t1; /* bottom-right */ | |
9518 }; | |
9519 | |
9520 struct nk_tt_packedchar { | |
9521 unsigned short x0,y0,x1,y1; | |
9522 /* coordinates of bbox in bitmap */ | |
9523 float xoff,yoff,xadvance; | |
9524 float xoff2,yoff2; | |
9525 }; | |
9526 | |
9527 struct nk_tt_pack_range { | |
9528 float font_size; | |
9529 int first_unicode_codepoint_in_range; | |
9530 /* if non-zero, then the chars are continuous, and this is the first codepoint */ | |
9531 int *array_of_unicode_codepoints; | |
9532 /* if non-zero, then this is an array of unicode codepoints */ | |
9533 int num_chars; | |
9534 struct nk_tt_packedchar *chardata_for_range; /* output */ | |
9535 unsigned char h_oversample, v_oversample; | |
9536 /* don't set these, they're used internally */ | |
9537 }; | |
9538 | |
9539 struct nk_tt_pack_context { | |
9540 void *pack_info; | |
9541 int width; | |
9542 int height; | |
9543 int stride_in_bytes; | |
9544 int padding; | |
9545 unsigned int h_oversample, v_oversample; | |
9546 unsigned char *pixels; | |
9547 void *nodes; | |
9548 }; | |
9549 | |
9550 struct nk_tt_fontinfo { | |
9551 const unsigned char* data; /* pointer to .ttf file */ | |
9552 int fontstart;/* offset of start of font */ | |
9553 int numGlyphs;/* number of glyphs, needed for range checking */ | |
9554 int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */ | |
9555 int index_map; /* a cmap mapping for our chosen character encoding */ | |
9556 int indexToLocFormat; /* format needed to map from glyph index to glyph */ | |
9557 }; | |
9558 | |
9559 enum { | |
9560 NK_TT_vmove=1, | |
9561 NK_TT_vline, | |
9562 NK_TT_vcurve | |
9563 }; | |
9564 | |
9565 struct nk_tt_vertex { | |
9566 short x,y,cx,cy; | |
9567 unsigned char type,padding; | |
9568 }; | |
9569 | |
9570 struct nk_tt__bitmap{ | |
9571 int w,h,stride; | |
9572 unsigned char *pixels; | |
9573 }; | |
9574 | |
9575 struct nk_tt__hheap_chunk { | |
9576 struct nk_tt__hheap_chunk *next; | |
9577 }; | |
9578 struct nk_tt__hheap { | |
9579 struct nk_allocator alloc; | |
9580 struct nk_tt__hheap_chunk *head; | |
9581 void *first_free; | |
9582 int num_remaining_in_head_chunk; | |
9583 }; | |
9584 | |
9585 struct nk_tt__edge { | |
9586 float x0,y0, x1,y1; | |
9587 int invert; | |
9588 }; | |
9589 | |
9590 struct nk_tt__active_edge { | |
9591 struct nk_tt__active_edge *next; | |
9592 float fx,fdx,fdy; | |
9593 float direction; | |
9594 float sy; | |
9595 float ey; | |
9596 }; | |
9597 struct nk_tt__point {float x,y;}; | |
9598 | |
9599 #define NK_TT_MACSTYLE_DONTCARE 0 | |
9600 #define NK_TT_MACSTYLE_BOLD 1 | |
9601 #define NK_TT_MACSTYLE_ITALIC 2 | |
9602 #define NK_TT_MACSTYLE_UNDERSCORE 4 | |
9603 #define NK_TT_MACSTYLE_NONE 8 | |
9604 /* <= not same as 0, this makes us check the bitfield is 0 */ | |
9605 | |
9606 enum { /* platformID */ | |
9607 NK_TT_PLATFORM_ID_UNICODE =0, | |
9608 NK_TT_PLATFORM_ID_MAC =1, | |
9609 NK_TT_PLATFORM_ID_ISO =2, | |
9610 NK_TT_PLATFORM_ID_MICROSOFT =3 | |
9611 }; | |
9612 | |
9613 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */ | |
9614 NK_TT_UNICODE_EID_UNICODE_1_0 =0, | |
9615 NK_TT_UNICODE_EID_UNICODE_1_1 =1, | |
9616 NK_TT_UNICODE_EID_ISO_10646 =2, | |
9617 NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3, | |
9618 NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4 | |
9619 }; | |
9620 | |
9621 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */ | |
9622 NK_TT_MS_EID_SYMBOL =0, | |
9623 NK_TT_MS_EID_UNICODE_BMP =1, | |
9624 NK_TT_MS_EID_SHIFTJIS =2, | |
9625 NK_TT_MS_EID_UNICODE_FULL =10 | |
9626 }; | |
9627 | |
9628 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */ | |
9629 NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4, | |
9630 NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5, | |
9631 NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6, | |
9632 NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7 | |
9633 }; | |
9634 | |
9635 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */ | |
9636 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ | |
9637 NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410, | |
9638 NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411, | |
9639 NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412, | |
9640 NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419, | |
9641 NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409, | |
9642 NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D | |
9643 }; | |
9644 | |
9645 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */ | |
9646 NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11, | |
9647 NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23, | |
9648 NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32, | |
9649 NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 , | |
9650 NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 , | |
9651 NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33, | |
9652 NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19 | |
9653 }; | |
9654 | |
9655 #define nk_ttBYTE(p) (* (const nk_byte *) (p)) | |
9656 #define nk_ttCHAR(p) (* (const char *) (p)) | |
9657 | |
9658 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE) | |
9659 #define nk_ttUSHORT(p) (* (nk_ushort *) (p)) | |
9660 #define nk_ttSHORT(p) (* (nk_short *) (p)) | |
9661 #define nk_ttULONG(p) (* (nk_uint *) (p)) | |
9662 #define nk_ttLONG(p) (* (nk_int *) (p)) | |
9663 #else | |
9664 static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); } | |
9665 static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); } | |
9666 static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); } | |
9667 #endif | |
9668 | |
9669 #define nk_tt_tag4(p,c0,c1,c2,c3)\ | |
9670 ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) | |
9671 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3]) | |
9672 | |
9673 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, | |
9674 int glyph_index, struct nk_tt_vertex **pvertices); | |
9675 | |
9676 NK_INTERN nk_uint | |
9677 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag) | |
9678 { | |
9679 /* @OPTIMIZE: binary search */ | |
9680 nk_int num_tables = nk_ttUSHORT(data+fontstart+4); | |
9681 nk_uint tabledir = fontstart + 12; | |
9682 nk_int i; | |
9683 for (i = 0; i < num_tables; ++i) { | |
9684 nk_uint loc = tabledir + (nk_uint)(16*i); | |
9685 if (nk_tt_tag(data+loc+0, tag)) | |
9686 return nk_ttULONG(data+loc+8); | |
9687 } | |
9688 return 0; | |
9689 } | |
9690 | |
9691 NK_INTERN int | |
9692 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart) | |
9693 { | |
9694 nk_uint cmap, t; | |
9695 nk_int i,numTables; | |
9696 const nk_byte *data = (const nk_byte *) data2; | |
9697 | |
9698 info->data = data; | |
9699 info->fontstart = fontstart; | |
9700 | |
9701 cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */ | |
9702 info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */ | |
9703 info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */ | |
9704 info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */ | |
9705 info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */ | |
9706 info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */ | |
9707 info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */ | |
9708 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) | |
9709 return 0; | |
9710 | |
9711 t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp"); | |
9712 if (t) info->numGlyphs = nk_ttUSHORT(data+t+4); | |
9713 else info->numGlyphs = 0xffff; | |
9714 | |
9715 /* find a cmap encoding table we understand *now* to avoid searching */ | |
9716 /* later. (todo: could make this installable) */ | |
9717 /* the same regardless of glyph. */ | |
9718 numTables = nk_ttUSHORT(data + cmap + 2); | |
9719 info->index_map = 0; | |
9720 for (i=0; i < numTables; ++i) | |
9721 { | |
9722 nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i; | |
9723 /* find an encoding we understand: */ | |
9724 switch(nk_ttUSHORT(data+encoding_record)) { | |
9725 case NK_TT_PLATFORM_ID_MICROSOFT: | |
9726 switch (nk_ttUSHORT(data+encoding_record+2)) { | |
9727 case NK_TT_MS_EID_UNICODE_BMP: | |
9728 case NK_TT_MS_EID_UNICODE_FULL: | |
9729 /* MS/Unicode */ | |
9730 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); | |
9731 break; | |
9732 default: break; | |
9733 } break; | |
9734 case NK_TT_PLATFORM_ID_UNICODE: | |
9735 /* Mac/iOS has these */ | |
9736 /* all the encodingIDs are unicode, so we don't bother to check it */ | |
9737 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); | |
9738 break; | |
9739 default: break; | |
9740 } | |
9741 } | |
9742 if (info->index_map == 0) | |
9743 return 0; | |
9744 info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50); | |
9745 return 1; | |
9746 } | |
9747 | |
9748 NK_INTERN int | |
9749 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint) | |
9750 { | |
9751 const nk_byte *data = info->data; | |
9752 nk_uint index_map = (nk_uint)info->index_map; | |
9753 | |
9754 nk_ushort format = nk_ttUSHORT(data + index_map + 0); | |
9755 if (format == 0) { /* apple byte encoding */ | |
9756 nk_int bytes = nk_ttUSHORT(data + index_map + 2); | |
9757 if (unicode_codepoint < bytes-6) | |
9758 return nk_ttBYTE(data + index_map + 6 + unicode_codepoint); | |
9759 return 0; | |
9760 } else if (format == 6) { | |
9761 nk_uint first = nk_ttUSHORT(data + index_map + 6); | |
9762 nk_uint count = nk_ttUSHORT(data + index_map + 8); | |
9763 if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count) | |
9764 return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2); | |
9765 return 0; | |
9766 } else if (format == 2) { | |
9767 NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ | |
9768 return 0; | |
9769 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ | |
9770 nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1; | |
9771 nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1; | |
9772 nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10); | |
9773 nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1; | |
9774 | |
9775 /* do a binary search of the segments */ | |
9776 nk_uint endCount = index_map + 14; | |
9777 nk_uint search = endCount; | |
9778 | |
9779 if (unicode_codepoint > 0xffff) | |
9780 return 0; | |
9781 | |
9782 /* they lie from endCount .. endCount + segCount */ | |
9783 /* but searchRange is the nearest power of two, so... */ | |
9784 if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2)) | |
9785 search += (nk_uint)(rangeShift*2); | |
9786 | |
9787 /* now decrement to bias correctly to find smallest */ | |
9788 search -= 2; | |
9789 while (entrySelector) { | |
9790 nk_ushort end; | |
9791 searchRange >>= 1; | |
9792 end = nk_ttUSHORT(data + search + searchRange*2); | |
9793 if (unicode_codepoint > end) | |
9794 search += (nk_uint)(searchRange*2); | |
9795 --entrySelector; | |
9796 } | |
9797 search += 2; | |
9798 | |
9799 { | |
9800 nk_ushort offset, start; | |
9801 nk_ushort item = (nk_ushort) ((search - endCount) >> 1); | |
9802 | |
9803 NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item)); | |
9804 start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); | |
9805 if (unicode_codepoint < start) | |
9806 return 0; | |
9807 | |
9808 offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); | |
9809 if (offset == 0) | |
9810 return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); | |
9811 | |
9812 return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); | |
9813 } | |
9814 } else if (format == 12 || format == 13) { | |
9815 nk_uint ngroups = nk_ttULONG(data+index_map+12); | |
9816 nk_int low,high; | |
9817 low = 0; high = (nk_int)ngroups; | |
9818 /* Binary search the right group. */ | |
9819 while (low < high) { | |
9820 nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ | |
9821 nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12); | |
9822 nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4); | |
9823 if ((nk_uint) unicode_codepoint < start_char) | |
9824 high = mid; | |
9825 else if ((nk_uint) unicode_codepoint > end_char) | |
9826 low = mid+1; | |
9827 else { | |
9828 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8); | |
9829 if (format == 12) | |
9830 return (int)start_glyph + (int)unicode_codepoint - (int)start_char; | |
9831 else /* format == 13 */ | |
9832 return (int)start_glyph; | |
9833 } | |
9834 } | |
9835 return 0; /* not found */ | |
9836 } | |
9837 /* @TODO */ | |
9838 NK_ASSERT(0); | |
9839 return 0; | |
9840 } | |
9841 | |
9842 NK_INTERN void | |
9843 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy) | |
9844 { | |
9845 v->type = type; | |
9846 v->x = (nk_short) x; | |
9847 v->y = (nk_short) y; | |
9848 v->cx = (nk_short) cx; | |
9849 v->cy = (nk_short) cy; | |
9850 } | |
9851 | |
9852 NK_INTERN int | |
9853 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index) | |
9854 { | |
9855 int g1,g2; | |
9856 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ | |
9857 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ | |
9858 | |
9859 if (info->indexToLocFormat == 0) { | |
9860 g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; | |
9861 g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; | |
9862 } else { | |
9863 g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4); | |
9864 g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4); | |
9865 } | |
9866 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ | |
9867 } | |
9868 | |
9869 NK_INTERN int | |
9870 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index, | |
9871 int *x0, int *y0, int *x1, int *y1) | |
9872 { | |
9873 int g = nk_tt__GetGlyfOffset(info, glyph_index); | |
9874 if (g < 0) return 0; | |
9875 | |
9876 if (x0) *x0 = nk_ttSHORT(info->data + g + 2); | |
9877 if (y0) *y0 = nk_ttSHORT(info->data + g + 4); | |
9878 if (x1) *x1 = nk_ttSHORT(info->data + g + 6); | |
9879 if (y1) *y1 = nk_ttSHORT(info->data + g + 8); | |
9880 return 1; | |
9881 } | |
9882 | |
9883 NK_INTERN int | |
9884 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off, | |
9885 int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy) | |
9886 { | |
9887 if (start_off) { | |
9888 if (was_off) | |
9889 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); | |
9890 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy); | |
9891 } else { | |
9892 if (was_off) | |
9893 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy); | |
9894 else | |
9895 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0); | |
9896 } | |
9897 return num_vertices; | |
9898 } | |
9899 | |
9900 NK_INTERN int | |
9901 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, | |
9902 int glyph_index, struct nk_tt_vertex **pvertices) | |
9903 { | |
9904 nk_short numberOfContours; | |
9905 const nk_byte *endPtsOfContours; | |
9906 const nk_byte *data = info->data; | |
9907 struct nk_tt_vertex *vertices=0; | |
9908 int num_vertices=0; | |
9909 int g = nk_tt__GetGlyfOffset(info, glyph_index); | |
9910 *pvertices = 0; | |
9911 | |
9912 if (g < 0) return 0; | |
9913 numberOfContours = nk_ttSHORT(data + g); | |
9914 if (numberOfContours > 0) { | |
9915 nk_byte flags=0,flagcount; | |
9916 nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; | |
9917 nk_int x,y,cx,cy,sx,sy, scx,scy; | |
9918 const nk_byte *points; | |
9919 endPtsOfContours = (data + g + 10); | |
9920 ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2); | |
9921 points = data + g + 10 + numberOfContours * 2 + 2 + ins; | |
9922 | |
9923 n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2); | |
9924 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ | |
9925 vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0])); | |
9926 if (vertices == 0) | |
9927 return 0; | |
9928 | |
9929 next_move = 0; | |
9930 flagcount=0; | |
9931 | |
9932 /* in first pass, we load uninterpreted data into the allocated array */ | |
9933 /* above, shifted to the end of the array so we won't overwrite it when */ | |
9934 /* we create our final data starting from the front */ | |
9935 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ | |
9936 | |
9937 /* first load flags */ | |
9938 for (i=0; i < n; ++i) { | |
9939 if (flagcount == 0) { | |
9940 flags = *points++; | |
9941 if (flags & 8) | |
9942 flagcount = *points++; | |
9943 } else --flagcount; | |
9944 vertices[off+i].type = flags; | |
9945 } | |
9946 | |
9947 /* now load x coordinates */ | |
9948 x=0; | |
9949 for (i=0; i < n; ++i) { | |
9950 flags = vertices[off+i].type; | |
9951 if (flags & 2) { | |
9952 nk_short dx = *points++; | |
9953 x += (flags & 16) ? dx : -dx; /* ??? */ | |
9954 } else { | |
9955 if (!(flags & 16)) { | |
9956 x = x + (nk_short) (points[0]*256 + points[1]); | |
9957 points += 2; | |
9958 } | |
9959 } | |
9960 vertices[off+i].x = (nk_short) x; | |
9961 } | |
9962 | |
9963 /* now load y coordinates */ | |
9964 y=0; | |
9965 for (i=0; i < n; ++i) { | |
9966 flags = vertices[off+i].type; | |
9967 if (flags & 4) { | |
9968 nk_short dy = *points++; | |
9969 y += (flags & 32) ? dy : -dy; /* ??? */ | |
9970 } else { | |
9971 if (!(flags & 32)) { | |
9972 y = y + (nk_short) (points[0]*256 + points[1]); | |
9973 points += 2; | |
9974 } | |
9975 } | |
9976 vertices[off+i].y = (nk_short) y; | |
9977 } | |
9978 | |
9979 /* now convert them to our format */ | |
9980 num_vertices=0; | |
9981 sx = sy = cx = cy = scx = scy = 0; | |
9982 for (i=0; i < n; ++i) | |
9983 { | |
9984 flags = vertices[off+i].type; | |
9985 x = (nk_short) vertices[off+i].x; | |
9986 y = (nk_short) vertices[off+i].y; | |
9987 | |
9988 if (next_move == i) { | |
9989 if (i != 0) | |
9990 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); | |
9991 | |
9992 /* now start the new one */ | |
9993 start_off = !(flags & 1); | |
9994 if (start_off) { | |
9995 /* if we start off with an off-curve point, then when we need to find a point on the curve */ | |
9996 /* where we can start, and we need to save some state for when we wraparound. */ | |
9997 scx = x; | |
9998 scy = y; | |
9999 if (!(vertices[off+i+1].type & 1)) { | |
10000 /* next point is also a curve point, so interpolate an on-point curve */ | |
10001 sx = (x + (nk_int) vertices[off+i+1].x) >> 1; | |
10002 sy = (y + (nk_int) vertices[off+i+1].y) >> 1; | |
10003 } else { | |
10004 /* otherwise just use the next point as our start point */ | |
10005 sx = (nk_int) vertices[off+i+1].x; | |
10006 sy = (nk_int) vertices[off+i+1].y; | |
10007 ++i; /* we're using point i+1 as the starting point, so skip it */ | |
10008 } | |
10009 } else { | |
10010 sx = x; | |
10011 sy = y; | |
10012 } | |
10013 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0); | |
10014 was_off = 0; | |
10015 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2); | |
10016 ++j; | |
10017 } else { | |
10018 if (!(flags & 1)) | |
10019 { /* if it's a curve */ | |
10020 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ | |
10021 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); | |
10022 cx = x; | |
10023 cy = y; | |
10024 was_off = 1; | |
10025 } else { | |
10026 if (was_off) | |
10027 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy); | |
10028 else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0); | |
10029 was_off = 0; | |
10030 } | |
10031 } | |
10032 } | |
10033 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); | |
10034 } else if (numberOfContours == -1) { | |
10035 /* Compound shapes. */ | |
10036 int more = 1; | |
10037 const nk_byte *comp = data + g + 10; | |
10038 num_vertices = 0; | |
10039 vertices = 0; | |
10040 | |
10041 while (more) | |
10042 { | |
10043 nk_ushort flags, gidx; | |
10044 int comp_num_verts = 0, i; | |
10045 struct nk_tt_vertex *comp_verts = 0, *tmp = 0; | |
10046 float mtx[6] = {1,0,0,1,0,0}, m, n; | |
10047 | |
10048 flags = (nk_ushort)nk_ttSHORT(comp); comp+=2; | |
10049 gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2; | |
10050 | |
10051 if (flags & 2) { /* XY values */ | |
10052 if (flags & 1) { /* shorts */ | |
10053 mtx[4] = nk_ttSHORT(comp); comp+=2; | |
10054 mtx[5] = nk_ttSHORT(comp); comp+=2; | |
10055 } else { | |
10056 mtx[4] = nk_ttCHAR(comp); comp+=1; | |
10057 mtx[5] = nk_ttCHAR(comp); comp+=1; | |
10058 } | |
10059 } else { | |
10060 /* @TODO handle matching point */ | |
10061 NK_ASSERT(0); | |
10062 } | |
10063 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ | |
10064 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10065 mtx[1] = mtx[2] = 0; | |
10066 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ | |
10067 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10068 mtx[1] = mtx[2] = 0; | |
10069 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10070 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ | |
10071 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10072 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10073 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10074 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; | |
10075 } | |
10076 | |
10077 /* Find transformation scales. */ | |
10078 m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]); | |
10079 n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]); | |
10080 | |
10081 /* Get indexed glyph. */ | |
10082 comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts); | |
10083 if (comp_num_verts > 0) | |
10084 { | |
10085 /* Transform vertices. */ | |
10086 for (i = 0; i < comp_num_verts; ++i) { | |
10087 struct nk_tt_vertex* v = &comp_verts[i]; | |
10088 short x,y; | |
10089 x=v->x; y=v->y; | |
10090 v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); | |
10091 v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); | |
10092 x=v->cx; y=v->cy; | |
10093 v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); | |
10094 v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); | |
10095 } | |
10096 /* Append vertices. */ | |
10097 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0, | |
10098 (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex)); | |
10099 if (!tmp) { | |
10100 if (vertices) alloc->free(alloc->userdata, vertices); | |
10101 if (comp_verts) alloc->free(alloc->userdata, comp_verts); | |
10102 return 0; | |
10103 } | |
10104 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex)); | |
10105 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex)); | |
10106 if (vertices) alloc->free(alloc->userdata,vertices); | |
10107 vertices = tmp; | |
10108 alloc->free(alloc->userdata,comp_verts); | |
10109 num_vertices += comp_num_verts; | |
10110 } | |
10111 /* More components ? */ | |
10112 more = flags & (1<<5); | |
10113 } | |
10114 } else if (numberOfContours < 0) { | |
10115 /* @TODO other compound variations? */ | |
10116 NK_ASSERT(0); | |
10117 } else { | |
10118 /* numberOfCounters == 0, do nothing */ | |
10119 } | |
10120 *pvertices = vertices; | |
10121 return num_vertices; | |
10122 } | |
10123 | |
10124 NK_INTERN void | |
10125 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index, | |
10126 int *advanceWidth, int *leftSideBearing) | |
10127 { | |
10128 nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34); | |
10129 if (glyph_index < numOfLongHorMetrics) { | |
10130 if (advanceWidth) | |
10131 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index); | |
10132 if (leftSideBearing) | |
10133 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); | |
10134 } else { | |
10135 if (advanceWidth) | |
10136 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); | |
10137 if (leftSideBearing) | |
10138 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); | |
10139 } | |
10140 } | |
10141 | |
10142 NK_INTERN void | |
10143 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info, | |
10144 int *ascent, int *descent, int *lineGap) | |
10145 { | |
10146 if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4); | |
10147 if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6); | |
10148 if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8); | |
10149 } | |
10150 | |
10151 NK_INTERN float | |
10152 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height) | |
10153 { | |
10154 int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6); | |
10155 return (float) height / (float)fheight; | |
10156 } | |
10157 | |
10158 NK_INTERN float | |
10159 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels) | |
10160 { | |
10161 int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18); | |
10162 return pixels / (float)unitsPerEm; | |
10163 } | |
10164 | |
10165 /*------------------------------------------------------------- | |
10166 * antialiasing software rasterizer | |
10167 * --------------------------------------------------------------*/ | |
10168 NK_INTERN void | |
10169 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font, | |
10170 int glyph, float scale_x, float scale_y,float shift_x, float shift_y, | |
10171 int *ix0, int *iy0, int *ix1, int *iy1) | |
10172 { | |
10173 int x0,y0,x1,y1; | |
10174 if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { | |
10175 /* e.g. space character */ | |
10176 if (ix0) *ix0 = 0; | |
10177 if (iy0) *iy0 = 0; | |
10178 if (ix1) *ix1 = 0; | |
10179 if (iy1) *iy1 = 0; | |
10180 } else { | |
10181 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ | |
10182 if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x); | |
10183 if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y); | |
10184 if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x); | |
10185 if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y); | |
10186 } | |
10187 } | |
10188 | |
10189 NK_INTERN void | |
10190 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph, | |
10191 float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) | |
10192 { | |
10193 nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); | |
10194 } | |
10195 | |
10196 /*------------------------------------------------------------- | |
10197 * Rasterizer | |
10198 * --------------------------------------------------------------*/ | |
10199 NK_INTERN void* | |
10200 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size) | |
10201 { | |
10202 if (hh->first_free) { | |
10203 void *p = hh->first_free; | |
10204 hh->first_free = * (void **) p; | |
10205 return p; | |
10206 } else { | |
10207 if (hh->num_remaining_in_head_chunk == 0) { | |
10208 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); | |
10209 struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *) | |
10210 hh->alloc.alloc(hh->alloc.userdata, 0, | |
10211 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count); | |
10212 if (c == 0) return 0; | |
10213 c->next = hh->head; | |
10214 hh->head = c; | |
10215 hh->num_remaining_in_head_chunk = count; | |
10216 } | |
10217 --hh->num_remaining_in_head_chunk; | |
10218 return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk; | |
10219 } | |
10220 } | |
10221 | |
10222 NK_INTERN void | |
10223 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p) | |
10224 { | |
10225 *(void **) p = hh->first_free; | |
10226 hh->first_free = p; | |
10227 } | |
10228 | |
10229 NK_INTERN void | |
10230 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh) | |
10231 { | |
10232 struct nk_tt__hheap_chunk *c = hh->head; | |
10233 while (c) { | |
10234 struct nk_tt__hheap_chunk *n = c->next; | |
10235 hh->alloc.free(hh->alloc.userdata, c); | |
10236 c = n; | |
10237 } | |
10238 } | |
10239 | |
10240 NK_INTERN struct nk_tt__active_edge* | |
10241 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e, | |
10242 int off_x, float start_point) | |
10243 { | |
10244 struct nk_tt__active_edge *z = (struct nk_tt__active_edge *) | |
10245 nk_tt__hheap_alloc(hh, sizeof(*z)); | |
10246 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); | |
10247 /*STBTT_assert(e->y0 <= start_point); */ | |
10248 if (!z) return z; | |
10249 z->fdx = dxdy; | |
10250 z->fdy = (dxdy != 0) ? (1/dxdy): 0; | |
10251 z->fx = e->x0 + dxdy * (start_point - e->y0); | |
10252 z->fx -= (float)off_x; | |
10253 z->direction = e->invert ? 1.0f : -1.0f; | |
10254 z->sy = e->y0; | |
10255 z->ey = e->y1; | |
10256 z->next = 0; | |
10257 return z; | |
10258 } | |
10259 | |
10260 NK_INTERN void | |
10261 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e, | |
10262 float x0, float y0, float x1, float y1) | |
10263 { | |
10264 if (y0 == y1) return; | |
10265 NK_ASSERT(y0 < y1); | |
10266 NK_ASSERT(e->sy <= e->ey); | |
10267 if (y0 > e->ey) return; | |
10268 if (y1 < e->sy) return; | |
10269 if (y0 < e->sy) { | |
10270 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); | |
10271 y0 = e->sy; | |
10272 } | |
10273 if (y1 > e->ey) { | |
10274 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); | |
10275 y1 = e->ey; | |
10276 } | |
10277 | |
10278 if (x0 == x) NK_ASSERT(x1 <= x+1); | |
10279 else if (x0 == x+1) NK_ASSERT(x1 >= x); | |
10280 else if (x0 <= x) NK_ASSERT(x1 <= x); | |
10281 else if (x0 >= x+1) NK_ASSERT(x1 >= x+1); | |
10282 else NK_ASSERT(x1 >= x && x1 <= x+1); | |
10283 | |
10284 if (x0 <= x && x1 <= x) | |
10285 scanline[x] += e->direction * (y1-y0); | |
10286 else if (x0 >= x+1 && x1 >= x+1); | |
10287 else { | |
10288 NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); | |
10289 /* coverage = 1 - average x position */ | |
10290 scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f); | |
10291 } | |
10292 } | |
10293 | |
10294 NK_INTERN void | |
10295 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, | |
10296 struct nk_tt__active_edge *e, float y_top) | |
10297 { | |
10298 float y_bottom = y_top+1; | |
10299 while (e) | |
10300 { | |
10301 /* brute force every pixel */ | |
10302 /* compute intersection points with top & bottom */ | |
10303 NK_ASSERT(e->ey >= y_top); | |
10304 if (e->fdx == 0) { | |
10305 float x0 = e->fx; | |
10306 if (x0 < len) { | |
10307 if (x0 >= 0) { | |
10308 nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); | |
10309 nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); | |
10310 } else { | |
10311 nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); | |
10312 } | |
10313 } | |
10314 } else { | |
10315 float x0 = e->fx; | |
10316 float dx = e->fdx; | |
10317 float xb = x0 + dx; | |
10318 float x_top, x_bottom; | |
10319 float y0,y1; | |
10320 float dy = e->fdy; | |
10321 NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top); | |
10322 | |
10323 /* compute endpoints of line segment clipped to this scanline (if the */ | |
10324 /* line segment starts on this scanline. x0 is the intersection of the */ | |
10325 /* line with y_top, but that may be off the line segment. */ | |
10326 if (e->sy > y_top) { | |
10327 x_top = x0 + dx * (e->sy - y_top); | |
10328 y0 = e->sy; | |
10329 } else { | |
10330 x_top = x0; | |
10331 y0 = y_top; | |
10332 } | |
10333 | |
10334 if (e->ey < y_bottom) { | |
10335 x_bottom = x0 + dx * (e->ey - y_top); | |
10336 y1 = e->ey; | |
10337 } else { | |
10338 x_bottom = xb; | |
10339 y1 = y_bottom; | |
10340 } | |
10341 | |
10342 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) | |
10343 { | |
10344 /* from here on, we don't have to range check x values */ | |
10345 if ((int) x_top == (int) x_bottom) { | |
10346 float height; | |
10347 /* simple case, only spans one pixel */ | |
10348 int x = (int) x_top; | |
10349 height = y1 - y0; | |
10350 NK_ASSERT(x >= 0 && x < len); | |
10351 scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height; | |
10352 scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */ | |
10353 } else { | |
10354 int x,x1,x2; | |
10355 float y_crossing, step, sign, area; | |
10356 /* covers 2+ pixels */ | |
10357 if (x_top > x_bottom) | |
10358 { | |
10359 /* flip scanline vertically; signed area is the same */ | |
10360 float t; | |
10361 y0 = y_bottom - (y0 - y_top); | |
10362 y1 = y_bottom - (y1 - y_top); | |
10363 t = y0; y0 = y1; y1 = t; | |
10364 t = x_bottom; x_bottom = x_top; x_top = t; | |
10365 dx = -dx; | |
10366 dy = -dy; | |
10367 t = x0; x0 = xb; xb = t; | |
10368 } | |
10369 | |
10370 x1 = (int) x_top; | |
10371 x2 = (int) x_bottom; | |
10372 /* compute intersection with y axis at x1+1 */ | |
10373 y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top; | |
10374 | |
10375 sign = e->direction; | |
10376 /* area of the rectangle covered from y0..y_crossing */ | |
10377 area = sign * (y_crossing-y0); | |
10378 /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */ | |
10379 scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f); | |
10380 | |
10381 step = sign * dy; | |
10382 for (x = x1+1; x < x2; ++x) { | |
10383 scanline[x] += area + step/2; | |
10384 area += step; | |
10385 } | |
10386 y_crossing += (float)dy * (float)(x2 - (x1+1)); | |
10387 | |
10388 scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing); | |
10389 scanline_fill[x2] += sign * (y1-y0); | |
10390 } | |
10391 } | |
10392 else | |
10393 { | |
10394 /* if edge goes outside of box we're drawing, we require */ | |
10395 /* clipping logic. since this does not match the intended use */ | |
10396 /* of this library, we use a different, very slow brute */ | |
10397 /* force implementation */ | |
10398 int x; | |
10399 for (x=0; x < len; ++x) | |
10400 { | |
10401 /* cases: */ | |
10402 /* */ | |
10403 /* there can be up to two intersections with the pixel. any intersection */ | |
10404 /* with left or right edges can be handled by splitting into two (or three) */ | |
10405 /* regions. intersections with top & bottom do not necessitate case-wise logic. */ | |
10406 /* */ | |
10407 /* the old way of doing this found the intersections with the left & right edges, */ | |
10408 /* then used some simple logic to produce up to three segments in sorted order */ | |
10409 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ | |
10410 /* across the x border, then the corresponding y position might not be distinct */ | |
10411 /* from the other y segment, and it might ignored as an empty segment. to avoid */ | |
10412 /* that, we need to explicitly produce segments based on x positions. */ | |
10413 | |
10414 /* rename variables to clear pairs */ | |
10415 float ya = y_top; | |
10416 float x1 = (float) (x); | |
10417 float x2 = (float) (x+1); | |
10418 float x3 = xb; | |
10419 float y3 = y_bottom; | |
10420 float yb,y2; | |
10421 | |
10422 yb = ((float)x - x0) / dx + y_top; | |
10423 y2 = ((float)x+1 - x0) / dx + y_top; | |
10424 | |
10425 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ | |
10426 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); | |
10427 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2); | |
10428 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); | |
10429 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ | |
10430 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); | |
10431 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb); | |
10432 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); | |
10433 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ | |
10434 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); | |
10435 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); | |
10436 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ | |
10437 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); | |
10438 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); | |
10439 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ | |
10440 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); | |
10441 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); | |
10442 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ | |
10443 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); | |
10444 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); | |
10445 } else { /* one segment */ | |
10446 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3); | |
10447 } | |
10448 } | |
10449 } | |
10450 } | |
10451 e = e->next; | |
10452 } | |
10453 } | |
10454 | |
10455 /* directly AA rasterize edges w/o supersampling */ | |
10456 NK_INTERN void | |
10457 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e, | |
10458 int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc) | |
10459 { | |
10460 struct nk_tt__hheap hh; | |
10461 struct nk_tt__active_edge *active = 0; | |
10462 int y,j=0, i; | |
10463 float scanline_data[129], *scanline, *scanline2; | |
10464 | |
10465 NK_UNUSED(vsubsample); | |
10466 nk_zero_struct(hh); | |
10467 hh.alloc = *alloc; | |
10468 | |
10469 if (result->w > 64) | |
10470 scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float)); | |
10471 else scanline = scanline_data; | |
10472 | |
10473 scanline2 = scanline + result->w; | |
10474 y = off_y; | |
10475 e[n].y0 = (float) (off_y + result->h) + 1; | |
10476 | |
10477 while (j < result->h) | |
10478 { | |
10479 /* find center of pixel for this scanline */ | |
10480 float scan_y_top = (float)y + 0.0f; | |
10481 float scan_y_bottom = (float)y + 1.0f; | |
10482 struct nk_tt__active_edge **step = &active; | |
10483 | |
10484 NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0])); | |
10485 NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0])); | |
10486 | |
10487 /* update all active edges; */ | |
10488 /* remove all active edges that terminate before the top of this scanline */ | |
10489 while (*step) { | |
10490 struct nk_tt__active_edge * z = *step; | |
10491 if (z->ey <= scan_y_top) { | |
10492 *step = z->next; /* delete from list */ | |
10493 NK_ASSERT(z->direction); | |
10494 z->direction = 0; | |
10495 nk_tt__hheap_free(&hh, z); | |
10496 } else { | |
10497 step = &((*step)->next); /* advance through list */ | |
10498 } | |
10499 } | |
10500 | |
10501 /* insert all edges that start before the bottom of this scanline */ | |
10502 while (e->y0 <= scan_y_bottom) { | |
10503 if (e->y0 != e->y1) { | |
10504 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top); | |
10505 if (z != 0) { | |
10506 NK_ASSERT(z->ey >= scan_y_top); | |
10507 /* insert at front */ | |
10508 z->next = active; | |
10509 active = z; | |
10510 } | |
10511 } | |
10512 ++e; | |
10513 } | |
10514 | |
10515 /* now process all active edges */ | |
10516 if (active) | |
10517 nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); | |
10518 | |
10519 { | |
10520 float sum = 0; | |
10521 for (i=0; i < result->w; ++i) { | |
10522 float k; | |
10523 int m; | |
10524 sum += scanline2[i]; | |
10525 k = scanline[i] + sum; | |
10526 k = (float) NK_ABS(k) * 255.0f + 0.5f; | |
10527 m = (int) k; | |
10528 if (m > 255) m = 255; | |
10529 result->pixels[j*result->stride + i] = (unsigned char) m; | |
10530 } | |
10531 } | |
10532 /* advance all the edges */ | |
10533 step = &active; | |
10534 while (*step) { | |
10535 struct nk_tt__active_edge *z = *step; | |
10536 z->fx += z->fdx; /* advance to position for current scanline */ | |
10537 step = &((*step)->next); /* advance through list */ | |
10538 } | |
10539 ++y; | |
10540 ++j; | |
10541 } | |
10542 nk_tt__hheap_cleanup(&hh); | |
10543 if (scanline != scanline_data) | |
10544 alloc->free(alloc->userdata, scanline); | |
10545 } | |
10546 | |
10547 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0) | |
10548 NK_INTERN void | |
10549 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n) | |
10550 { | |
10551 int i,j; | |
10552 for (i=1; i < n; ++i) { | |
10553 struct nk_tt__edge t = p[i], *a = &t; | |
10554 j = i; | |
10555 while (j > 0) { | |
10556 struct nk_tt__edge *b = &p[j-1]; | |
10557 int c = NK_TT__COMPARE(a,b); | |
10558 if (!c) break; | |
10559 p[j] = p[j-1]; | |
10560 --j; | |
10561 } | |
10562 if (i != j) | |
10563 p[j] = t; | |
10564 } | |
10565 } | |
10566 | |
10567 NK_INTERN void | |
10568 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n) | |
10569 { | |
10570 /* threshold for transitioning to insertion sort */ | |
10571 while (n > 12) { | |
10572 struct nk_tt__edge t; | |
10573 int c01,c12,c,m,i,j; | |
10574 | |
10575 /* compute median of three */ | |
10576 m = n >> 1; | |
10577 c01 = NK_TT__COMPARE(&p[0],&p[m]); | |
10578 c12 = NK_TT__COMPARE(&p[m],&p[n-1]); | |
10579 | |
10580 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ | |
10581 if (c01 != c12) { | |
10582 /* otherwise, we'll need to swap something else to middle */ | |
10583 int z; | |
10584 c = NK_TT__COMPARE(&p[0],&p[n-1]); | |
10585 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ | |
10586 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ | |
10587 z = (c == c12) ? 0 : n-1; | |
10588 t = p[z]; | |
10589 p[z] = p[m]; | |
10590 p[m] = t; | |
10591 } | |
10592 | |
10593 /* now p[m] is the median-of-three */ | |
10594 /* swap it to the beginning so it won't move around */ | |
10595 t = p[0]; | |
10596 p[0] = p[m]; | |
10597 p[m] = t; | |
10598 | |
10599 /* partition loop */ | |
10600 i=1; | |
10601 j=n-1; | |
10602 for(;;) { | |
10603 /* handling of equality is crucial here */ | |
10604 /* for sentinels & efficiency with duplicates */ | |
10605 for (;;++i) { | |
10606 if (!NK_TT__COMPARE(&p[i], &p[0])) break; | |
10607 } | |
10608 for (;;--j) { | |
10609 if (!NK_TT__COMPARE(&p[0], &p[j])) break; | |
10610 } | |
10611 | |
10612 /* make sure we haven't crossed */ | |
10613 if (i >= j) break; | |
10614 t = p[i]; | |
10615 p[i] = p[j]; | |
10616 p[j] = t; | |
10617 | |
10618 ++i; | |
10619 --j; | |
10620 | |
10621 } | |
10622 | |
10623 /* recurse on smaller side, iterate on larger */ | |
10624 if (j < (n-i)) { | |
10625 nk_tt__sort_edges_quicksort(p,j); | |
10626 p = p+i; | |
10627 n = n-i; | |
10628 } else { | |
10629 nk_tt__sort_edges_quicksort(p+i, n-i); | |
10630 n = j; | |
10631 } | |
10632 } | |
10633 } | |
10634 | |
10635 NK_INTERN void | |
10636 nk_tt__sort_edges(struct nk_tt__edge *p, int n) | |
10637 { | |
10638 nk_tt__sort_edges_quicksort(p, n); | |
10639 nk_tt__sort_edges_ins_sort(p, n); | |
10640 } | |
10641 | |
10642 NK_INTERN void | |
10643 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts, | |
10644 int *wcount, int windings, float scale_x, float scale_y, | |
10645 float shift_x, float shift_y, int off_x, int off_y, int invert, | |
10646 struct nk_allocator *alloc) | |
10647 { | |
10648 float y_scale_inv = invert ? -scale_y : scale_y; | |
10649 struct nk_tt__edge *e; | |
10650 int n,i,j,k,m; | |
10651 int vsubsample = 1; | |
10652 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ | |
10653 | |
10654 /* now we have to blow out the windings into explicit edge lists */ | |
10655 n = 0; | |
10656 for (i=0; i < windings; ++i) | |
10657 n += wcount[i]; | |
10658 | |
10659 e = (struct nk_tt__edge*) | |
10660 alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1))); | |
10661 if (e == 0) return; | |
10662 n = 0; | |
10663 | |
10664 m=0; | |
10665 for (i=0; i < windings; ++i) | |
10666 { | |
10667 struct nk_tt__point *p = pts + m; | |
10668 m += wcount[i]; | |
10669 j = wcount[i]-1; | |
10670 for (k=0; k < wcount[i]; j=k++) { | |
10671 int a=k,b=j; | |
10672 /* skip the edge if horizontal */ | |
10673 if (p[j].y == p[k].y) | |
10674 continue; | |
10675 | |
10676 /* add edge from j to k to the list */ | |
10677 e[n].invert = 0; | |
10678 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { | |
10679 e[n].invert = 1; | |
10680 a=j,b=k; | |
10681 } | |
10682 e[n].x0 = p[a].x * scale_x + shift_x; | |
10683 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample; | |
10684 e[n].x1 = p[b].x * scale_x + shift_x; | |
10685 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample; | |
10686 ++n; | |
10687 } | |
10688 } | |
10689 | |
10690 /* now sort the edges by their highest point (should snap to integer, and then by x) */ | |
10691 /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */ | |
10692 nk_tt__sort_edges(e, n); | |
10693 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ | |
10694 nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc); | |
10695 alloc->free(alloc->userdata, e); | |
10696 } | |
10697 | |
10698 NK_INTERN void | |
10699 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y) | |
10700 { | |
10701 if (!points) return; /* during first pass, it's unallocated */ | |
10702 points[n].x = x; | |
10703 points[n].y = y; | |
10704 } | |
10705 | |
10706 NK_INTERN int | |
10707 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points, | |
10708 float x0, float y0, float x1, float y1, float x2, float y2, | |
10709 float objspace_flatness_squared, int n) | |
10710 { | |
10711 /* tesselate until threshold p is happy... | |
10712 * @TODO warped to compensate for non-linear stretching */ | |
10713 /* midpoint */ | |
10714 float mx = (x0 + 2*x1 + x2)/4; | |
10715 float my = (y0 + 2*y1 + y2)/4; | |
10716 /* versus directly drawn line */ | |
10717 float dx = (x0+x2)/2 - mx; | |
10718 float dy = (y0+y2)/2 - my; | |
10719 if (n > 16) /* 65536 segments on one curve better be enough! */ | |
10720 return 1; | |
10721 | |
10722 /* half-pixel error allowed... need to be smaller if AA */ | |
10723 if (dx*dx+dy*dy > objspace_flatness_squared) { | |
10724 nk_tt__tesselate_curve(points, num_points, x0,y0, | |
10725 (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); | |
10726 nk_tt__tesselate_curve(points, num_points, mx,my, | |
10727 (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); | |
10728 } else { | |
10729 nk_tt__add_point(points, *num_points,x2,y2); | |
10730 *num_points = *num_points+1; | |
10731 } | |
10732 return 1; | |
10733 } | |
10734 | |
10735 /* returns number of contours */ | |
10736 NK_INTERN struct nk_tt__point* | |
10737 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts, | |
10738 float objspace_flatness, int **contour_lengths, int *num_contours, | |
10739 struct nk_allocator *alloc) | |
10740 { | |
10741 struct nk_tt__point *points=0; | |
10742 int num_points=0; | |
10743 float objspace_flatness_squared = objspace_flatness * objspace_flatness; | |
10744 int i; | |
10745 int n=0; | |
10746 int start=0; | |
10747 int pass; | |
10748 | |
10749 /* count how many "moves" there are to get the contour count */ | |
10750 for (i=0; i < num_verts; ++i) | |
10751 if (vertices[i].type == NK_TT_vmove) ++n; | |
10752 | |
10753 *num_contours = n; | |
10754 if (n == 0) return 0; | |
10755 | |
10756 *contour_lengths = (int *) | |
10757 alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n)); | |
10758 if (*contour_lengths == 0) { | |
10759 *num_contours = 0; | |
10760 return 0; | |
10761 } | |
10762 | |
10763 /* make two passes through the points so we don't need to realloc */ | |
10764 for (pass=0; pass < 2; ++pass) | |
10765 { | |
10766 float x=0,y=0; | |
10767 if (pass == 1) { | |
10768 points = (struct nk_tt__point *) | |
10769 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0])); | |
10770 if (points == 0) goto error; | |
10771 } | |
10772 num_points = 0; | |
10773 n= -1; | |
10774 | |
10775 for (i=0; i < num_verts; ++i) | |
10776 { | |
10777 switch (vertices[i].type) { | |
10778 case NK_TT_vmove: | |
10779 /* start the next contour */ | |
10780 if (n >= 0) | |
10781 (*contour_lengths)[n] = num_points - start; | |
10782 ++n; | |
10783 start = num_points; | |
10784 | |
10785 x = vertices[i].x, y = vertices[i].y; | |
10786 nk_tt__add_point(points, num_points++, x,y); | |
10787 break; | |
10788 case NK_TT_vline: | |
10789 x = vertices[i].x, y = vertices[i].y; | |
10790 nk_tt__add_point(points, num_points++, x, y); | |
10791 break; | |
10792 case NK_TT_vcurve: | |
10793 nk_tt__tesselate_curve(points, &num_points, x,y, | |
10794 vertices[i].cx, vertices[i].cy, | |
10795 vertices[i].x, vertices[i].y, | |
10796 objspace_flatness_squared, 0); | |
10797 x = vertices[i].x, y = vertices[i].y; | |
10798 break; | |
10799 default: break; | |
10800 } | |
10801 } | |
10802 (*contour_lengths)[n] = num_points - start; | |
10803 } | |
10804 return points; | |
10805 | |
10806 error: | |
10807 alloc->free(alloc->userdata, points); | |
10808 alloc->free(alloc->userdata, *contour_lengths); | |
10809 *contour_lengths = 0; | |
10810 *num_contours = 0; | |
10811 return 0; | |
10812 } | |
10813 | |
10814 NK_INTERN void | |
10815 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels, | |
10816 struct nk_tt_vertex *vertices, int num_verts, | |
10817 float scale_x, float scale_y, float shift_x, float shift_y, | |
10818 int x_off, int y_off, int invert, struct nk_allocator *alloc) | |
10819 { | |
10820 float scale = scale_x > scale_y ? scale_y : scale_x; | |
10821 int winding_count, *winding_lengths; | |
10822 struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts, | |
10823 flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc); | |
10824 | |
10825 NK_ASSERT(alloc); | |
10826 if (windings) { | |
10827 nk_tt__rasterize(result, windings, winding_lengths, winding_count, | |
10828 scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc); | |
10829 alloc->free(alloc->userdata, winding_lengths); | |
10830 alloc->free(alloc->userdata, windings); | |
10831 } | |
10832 } | |
10833 | |
10834 NK_INTERN void | |
10835 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output, | |
10836 int out_w, int out_h, int out_stride, float scale_x, float scale_y, | |
10837 float shift_x, float shift_y, int glyph, struct nk_allocator *alloc) | |
10838 { | |
10839 int ix0,iy0; | |
10840 struct nk_tt_vertex *vertices; | |
10841 int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices); | |
10842 struct nk_tt__bitmap gbm; | |
10843 | |
10844 nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, | |
10845 shift_y, &ix0,&iy0,0,0); | |
10846 gbm.pixels = output; | |
10847 gbm.w = out_w; | |
10848 gbm.h = out_h; | |
10849 gbm.stride = out_stride; | |
10850 | |
10851 if (gbm.w && gbm.h) | |
10852 nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, | |
10853 shift_x, shift_y, ix0,iy0, 1, alloc); | |
10854 alloc->free(alloc->userdata, vertices); | |
10855 } | |
10856 | |
10857 /*------------------------------------------------------------- | |
10858 * Bitmap baking | |
10859 * --------------------------------------------------------------*/ | |
10860 NK_INTERN int | |
10861 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels, | |
10862 int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc) | |
10863 { | |
10864 int num_nodes = pw - padding; | |
10865 struct nk_rp_context *context = (struct nk_rp_context *) | |
10866 alloc->alloc(alloc->userdata,0, sizeof(*context)); | |
10867 struct nk_rp_node *nodes = (struct nk_rp_node*) | |
10868 alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes)); | |
10869 | |
10870 if (context == 0 || nodes == 0) { | |
10871 if (context != 0) alloc->free(alloc->userdata, context); | |
10872 if (nodes != 0) alloc->free(alloc->userdata, nodes); | |
10873 return 0; | |
10874 } | |
10875 | |
10876 spc->width = pw; | |
10877 spc->height = ph; | |
10878 spc->pixels = pixels; | |
10879 spc->pack_info = context; | |
10880 spc->nodes = nodes; | |
10881 spc->padding = padding; | |
10882 spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw; | |
10883 spc->h_oversample = 1; | |
10884 spc->v_oversample = 1; | |
10885 | |
10886 nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); | |
10887 if (pixels) | |
10888 NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */ | |
10889 return 1; | |
10890 } | |
10891 | |
10892 NK_INTERN void | |
10893 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc) | |
10894 { | |
10895 alloc->free(alloc->userdata, spc->nodes); | |
10896 alloc->free(alloc->userdata, spc->pack_info); | |
10897 } | |
10898 | |
10899 NK_INTERN void | |
10900 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc, | |
10901 unsigned int h_oversample, unsigned int v_oversample) | |
10902 { | |
10903 NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE); | |
10904 NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE); | |
10905 if (h_oversample <= NK_TT_MAX_OVERSAMPLE) | |
10906 spc->h_oversample = h_oversample; | |
10907 if (v_oversample <= NK_TT_MAX_OVERSAMPLE) | |
10908 spc->v_oversample = v_oversample; | |
10909 } | |
10910 | |
10911 NK_INTERN void | |
10912 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, | |
10913 int kernel_width) | |
10914 { | |
10915 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; | |
10916 int safe_w = w - kernel_width; | |
10917 int j; | |
10918 | |
10919 for (j=0; j < h; ++j) | |
10920 { | |
10921 int i; | |
10922 unsigned int total; | |
10923 NK_MEMSET(buffer, 0, (nk_size)kernel_width); | |
10924 | |
10925 total = 0; | |
10926 | |
10927 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ | |
10928 switch (kernel_width) { | |
10929 case 2: | |
10930 for (i=0; i <= safe_w; ++i) { | |
10931 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); | |
10932 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; | |
10933 pixels[i] = (unsigned char) (total / 2); | |
10934 } | |
10935 break; | |
10936 case 3: | |
10937 for (i=0; i <= safe_w; ++i) { | |
10938 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); | |
10939 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; | |
10940 pixels[i] = (unsigned char) (total / 3); | |
10941 } | |
10942 break; | |
10943 case 4: | |
10944 for (i=0; i <= safe_w; ++i) { | |
10945 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK]; | |
10946 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; | |
10947 pixels[i] = (unsigned char) (total / 4); | |
10948 } | |
10949 break; | |
10950 case 5: | |
10951 for (i=0; i <= safe_w; ++i) { | |
10952 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); | |
10953 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; | |
10954 pixels[i] = (unsigned char) (total / 5); | |
10955 } | |
10956 break; | |
10957 default: | |
10958 for (i=0; i <= safe_w; ++i) { | |
10959 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); | |
10960 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; | |
10961 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); | |
10962 } | |
10963 break; | |
10964 } | |
10965 | |
10966 for (; i < w; ++i) { | |
10967 NK_ASSERT(pixels[i] == 0); | |
10968 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); | |
10969 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); | |
10970 } | |
10971 pixels += stride_in_bytes; | |
10972 } | |
10973 } | |
10974 | |
10975 NK_INTERN void | |
10976 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, | |
10977 int kernel_width) | |
10978 { | |
10979 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; | |
10980 int safe_h = h - kernel_width; | |
10981 int j; | |
10982 | |
10983 for (j=0; j < w; ++j) | |
10984 { | |
10985 int i; | |
10986 unsigned int total; | |
10987 NK_MEMSET(buffer, 0, (nk_size)kernel_width); | |
10988 | |
10989 total = 0; | |
10990 | |
10991 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ | |
10992 switch (kernel_width) { | |
10993 case 2: | |
10994 for (i=0; i <= safe_h; ++i) { | |
10995 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); | |
10996 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; | |
10997 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); | |
10998 } | |
10999 break; | |
11000 case 3: | |
11001 for (i=0; i <= safe_h; ++i) { | |
11002 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); | |
11003 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; | |
11004 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); | |
11005 } | |
11006 break; | |
11007 case 4: | |
11008 for (i=0; i <= safe_h; ++i) { | |
11009 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); | |
11010 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; | |
11011 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); | |
11012 } | |
11013 break; | |
11014 case 5: | |
11015 for (i=0; i <= safe_h; ++i) { | |
11016 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); | |
11017 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; | |
11018 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); | |
11019 } | |
11020 break; | |
11021 default: | |
11022 for (i=0; i <= safe_h; ++i) { | |
11023 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); | |
11024 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; | |
11025 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); | |
11026 } | |
11027 break; | |
11028 } | |
11029 | |
11030 for (; i < h; ++i) { | |
11031 NK_ASSERT(pixels[i*stride_in_bytes] == 0); | |
11032 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); | |
11033 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); | |
11034 } | |
11035 pixels += 1; | |
11036 } | |
11037 } | |
11038 | |
11039 NK_INTERN float | |
11040 nk_tt__oversample_shift(int oversample) | |
11041 { | |
11042 if (!oversample) | |
11043 return 0.0f; | |
11044 | |
11045 /* The prefilter is a box filter of width "oversample", */ | |
11046 /* which shifts phase by (oversample - 1)/2 pixels in */ | |
11047 /* oversampled space. We want to shift in the opposite */ | |
11048 /* direction to counter this. */ | |
11049 return (float)-(oversample - 1) / (2.0f * (float)oversample); | |
11050 } | |
11051 | |
11052 /* rects array must be big enough to accommodate all characters in the given ranges */ | |
11053 NK_INTERN int | |
11054 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc, | |
11055 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, | |
11056 int num_ranges, struct nk_rp_rect *rects) | |
11057 { | |
11058 int i,j,k; | |
11059 k = 0; | |
11060 | |
11061 for (i=0; i < num_ranges; ++i) { | |
11062 float fh = ranges[i].font_size; | |
11063 float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh): | |
11064 nk_tt_ScaleForMappingEmToPixels(info, -fh); | |
11065 ranges[i].h_oversample = (unsigned char) spc->h_oversample; | |
11066 ranges[i].v_oversample = (unsigned char) spc->v_oversample; | |
11067 for (j=0; j < ranges[i].num_chars; ++j) { | |
11068 int x0,y0,x1,y1; | |
11069 int codepoint = ranges[i].first_unicode_codepoint_in_range ? | |
11070 ranges[i].first_unicode_codepoint_in_range + j : | |
11071 ranges[i].array_of_unicode_codepoints[j]; | |
11072 | |
11073 int glyph = nk_tt_FindGlyphIndex(info, codepoint); | |
11074 nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample, | |
11075 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); | |
11076 rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1); | |
11077 rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1); | |
11078 ++k; | |
11079 } | |
11080 } | |
11081 return k; | |
11082 } | |
11083 | |
11084 NK_INTERN int | |
11085 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc, | |
11086 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, | |
11087 int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc) | |
11088 { | |
11089 int i,j,k, return_value = 1; | |
11090 /* save current values */ | |
11091 int old_h_over = (int)spc->h_oversample; | |
11092 int old_v_over = (int)spc->v_oversample; | |
11093 /* rects array must be big enough to accommodate all characters in the given ranges */ | |
11094 | |
11095 k = 0; | |
11096 for (i=0; i < num_ranges; ++i) | |
11097 { | |
11098 float fh = ranges[i].font_size; | |
11099 float recip_h,recip_v,sub_x,sub_y; | |
11100 float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh): | |
11101 nk_tt_ScaleForMappingEmToPixels(info, -fh); | |
11102 | |
11103 spc->h_oversample = ranges[i].h_oversample; | |
11104 spc->v_oversample = ranges[i].v_oversample; | |
11105 | |
11106 recip_h = 1.0f / (float)spc->h_oversample; | |
11107 recip_v = 1.0f / (float)spc->v_oversample; | |
11108 | |
11109 sub_x = nk_tt__oversample_shift((int)spc->h_oversample); | |
11110 sub_y = nk_tt__oversample_shift((int)spc->v_oversample); | |
11111 | |
11112 for (j=0; j < ranges[i].num_chars; ++j) | |
11113 { | |
11114 struct nk_rp_rect *r = &rects[k]; | |
11115 if (r->was_packed) | |
11116 { | |
11117 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j]; | |
11118 int advance, lsb, x0,y0,x1,y1; | |
11119 int codepoint = ranges[i].first_unicode_codepoint_in_range ? | |
11120 ranges[i].first_unicode_codepoint_in_range + j : | |
11121 ranges[i].array_of_unicode_codepoints[j]; | |
11122 int glyph = nk_tt_FindGlyphIndex(info, codepoint); | |
11123 nk_rp_coord pad = (nk_rp_coord) spc->padding; | |
11124 | |
11125 /* pad on left and top */ | |
11126 r->x = (nk_rp_coord)((int)r->x + (int)pad); | |
11127 r->y = (nk_rp_coord)((int)r->y + (int)pad); | |
11128 r->w = (nk_rp_coord)((int)r->w - (int)pad); | |
11129 r->h = (nk_rp_coord)((int)r->h - (int)pad); | |
11130 | |
11131 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb); | |
11132 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample, | |
11133 (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1); | |
11134 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, | |
11135 (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1), | |
11136 spc->stride_in_bytes, scale * (float)spc->h_oversample, | |
11137 scale * (float)spc->v_oversample, 0,0, glyph, alloc); | |
11138 | |
11139 if (spc->h_oversample > 1) | |
11140 nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, | |
11141 r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample); | |
11142 | |
11143 if (spc->v_oversample > 1) | |
11144 nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, | |
11145 r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample); | |
11146 | |
11147 bc->x0 = (nk_ushort) r->x; | |
11148 bc->y0 = (nk_ushort) r->y; | |
11149 bc->x1 = (nk_ushort) (r->x + r->w); | |
11150 bc->y1 = (nk_ushort) (r->y + r->h); | |
11151 bc->xadvance = scale * (float)advance; | |
11152 bc->xoff = (float) x0 * recip_h + sub_x; | |
11153 bc->yoff = (float) y0 * recip_v + sub_y; | |
11154 bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x; | |
11155 bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y; | |
11156 } else { | |
11157 return_value = 0; /* if any fail, report failure */ | |
11158 } | |
11159 ++k; | |
11160 } | |
11161 } | |
11162 /* restore original values */ | |
11163 spc->h_oversample = (unsigned int)old_h_over; | |
11164 spc->v_oversample = (unsigned int)old_v_over; | |
11165 return return_value; | |
11166 } | |
11167 | |
11168 NK_INTERN void | |
11169 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph, | |
11170 int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q, | |
11171 int align_to_integer) | |
11172 { | |
11173 float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph; | |
11174 struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index); | |
11175 if (align_to_integer) { | |
11176 int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f); | |
11177 int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f); | |
11178 | |
11179 float x = (float)tx; | |
11180 float y = (float)ty; | |
11181 | |
11182 q->x0 = x; | |
11183 q->y0 = y; | |
11184 q->x1 = x + b->xoff2 - b->xoff; | |
11185 q->y1 = y + b->yoff2 - b->yoff; | |
11186 } else { | |
11187 q->x0 = *xpos + b->xoff; | |
11188 q->y0 = *ypos + b->yoff; | |
11189 q->x1 = *xpos + b->xoff2; | |
11190 q->y1 = *ypos + b->yoff2; | |
11191 } | |
11192 q->s0 = b->x0 * ipw; | |
11193 q->t0 = b->y0 * iph; | |
11194 q->s1 = b->x1 * ipw; | |
11195 q->t1 = b->y1 * iph; | |
11196 *xpos += b->xadvance; | |
11197 } | |
11198 | |
11199 /* ------------------------------------------------------------- | |
11200 * | |
11201 * FONT BAKING | |
11202 * | |
11203 * --------------------------------------------------------------*/ | |
11204 struct nk_font_bake_data { | |
11205 struct nk_tt_fontinfo info; | |
11206 struct nk_rp_rect *rects; | |
11207 struct nk_tt_pack_range *ranges; | |
11208 nk_rune range_count; | |
11209 }; | |
11210 | |
11211 struct nk_font_baker { | |
11212 struct nk_allocator alloc; | |
11213 struct nk_tt_pack_context spc; | |
11214 struct nk_font_bake_data *build; | |
11215 struct nk_tt_packedchar *packed_chars; | |
11216 struct nk_rp_rect *rects; | |
11217 struct nk_tt_pack_range *ranges; | |
11218 }; | |
11219 | |
11220 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect); | |
11221 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range); | |
11222 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar); | |
11223 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); | |
11224 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); | |
11225 | |
11226 NK_INTERN int | |
11227 nk_range_count(const nk_rune *range) | |
11228 { | |
11229 const nk_rune *iter = range; | |
11230 NK_ASSERT(range); | |
11231 if (!range) return 0; | |
11232 while (*(iter++) != 0); | |
11233 return (iter == range) ? 0 : (int)((iter - range)/2); | |
11234 } | |
11235 | |
11236 NK_INTERN int | |
11237 nk_range_glyph_count(const nk_rune *range, int count) | |
11238 { | |
11239 int i = 0; | |
11240 int total_glyphs = 0; | |
11241 for (i = 0; i < count; ++i) { | |
11242 int diff; | |
11243 nk_rune f = range[(i*2)+0]; | |
11244 nk_rune t = range[(i*2)+1]; | |
11245 NK_ASSERT(t >= f); | |
11246 diff = (int)((t - f) + 1); | |
11247 total_glyphs += diff; | |
11248 } | |
11249 return total_glyphs; | |
11250 } | |
11251 | |
11252 NK_API const nk_rune* | |
11253 nk_font_default_glyph_ranges(void) | |
11254 { | |
11255 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; | |
11256 return ranges; | |
11257 } | |
11258 | |
11259 NK_API const nk_rune* | |
11260 nk_font_chinese_glyph_ranges(void) | |
11261 { | |
11262 NK_STORAGE const nk_rune ranges[] = { | |
11263 0x0020, 0x00FF, | |
11264 0x3000, 0x30FF, | |
11265 0x31F0, 0x31FF, | |
11266 0xFF00, 0xFFEF, | |
11267 0x4e00, 0x9FAF, | |
11268 0 | |
11269 }; | |
11270 return ranges; | |
11271 } | |
11272 | |
11273 NK_API const nk_rune* | |
11274 nk_font_cyrillic_glyph_ranges(void) | |
11275 { | |
11276 NK_STORAGE const nk_rune ranges[] = { | |
11277 0x0020, 0x00FF, | |
11278 0x0400, 0x052F, | |
11279 0x2DE0, 0x2DFF, | |
11280 0xA640, 0xA69F, | |
11281 0 | |
11282 }; | |
11283 return ranges; | |
11284 } | |
11285 | |
11286 NK_API const nk_rune* | |
11287 nk_font_korean_glyph_ranges(void) | |
11288 { | |
11289 NK_STORAGE const nk_rune ranges[] = { | |
11290 0x0020, 0x00FF, | |
11291 0x3131, 0x3163, | |
11292 0xAC00, 0xD79D, | |
11293 0 | |
11294 }; | |
11295 return ranges; | |
11296 } | |
11297 | |
11298 NK_INTERN void | |
11299 nk_font_baker_memory(nk_size *temp, int *glyph_count, | |
11300 struct nk_font_config *config_list, int count) | |
11301 { | |
11302 int range_count = 0; | |
11303 int total_range_count = 0; | |
11304 struct nk_font_config *iter; | |
11305 | |
11306 NK_ASSERT(config_list); | |
11307 NK_ASSERT(glyph_count); | |
11308 if (!config_list) { | |
11309 *temp = 0; | |
11310 *glyph_count = 0; | |
11311 return; | |
11312 } | |
11313 | |
11314 *glyph_count = 0; | |
11315 if (!config_list->range) | |
11316 config_list->range = nk_font_default_glyph_ranges(); | |
11317 for (iter = config_list; iter; iter = iter->next) { | |
11318 range_count = nk_range_count(iter->range); | |
11319 total_range_count += range_count; | |
11320 *glyph_count += nk_range_glyph_count(iter->range, range_count); | |
11321 } | |
11322 | |
11323 *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect); | |
11324 *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range); | |
11325 *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar); | |
11326 *temp += (nk_size)count * sizeof(struct nk_font_bake_data); | |
11327 *temp += sizeof(struct nk_font_baker); | |
11328 *temp += nk_rect_align + nk_range_align + nk_char_align; | |
11329 *temp += nk_build_align + nk_baker_align; | |
11330 } | |
11331 | |
11332 NK_INTERN struct nk_font_baker* | |
11333 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) | |
11334 { | |
11335 struct nk_font_baker *baker; | |
11336 if (!memory) return 0; | |
11337 /* setup baker inside a memory block */ | |
11338 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); | |
11339 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); | |
11340 baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); | |
11341 baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); | |
11342 baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); | |
11343 baker->alloc = *alloc; | |
11344 return baker; | |
11345 } | |
11346 | |
11347 NK_INTERN int | |
11348 nk_font_bake_pack(struct nk_font_baker *baker, | |
11349 nk_size *image_memory, int *width, int *height, struct nk_recti *custom, | |
11350 const struct nk_font_config *config_list, int count, | |
11351 struct nk_allocator *alloc) | |
11352 { | |
11353 NK_STORAGE const nk_size max_height = 1024 * 32; | |
11354 const struct nk_font_config *config_iter; | |
11355 int total_glyph_count = 0; | |
11356 int total_range_count = 0; | |
11357 int range_count = 0; | |
11358 int i = 0; | |
11359 | |
11360 NK_ASSERT(image_memory); | |
11361 NK_ASSERT(width); | |
11362 NK_ASSERT(height); | |
11363 NK_ASSERT(config_list); | |
11364 NK_ASSERT(count); | |
11365 NK_ASSERT(alloc); | |
11366 | |
11367 if (!image_memory || !width || !height || !config_list || !count) return nk_false; | |
11368 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { | |
11369 range_count = nk_range_count(config_iter->range); | |
11370 total_range_count += range_count; | |
11371 total_glyph_count += nk_range_glyph_count(config_iter->range, range_count); | |
11372 } | |
11373 | |
11374 /* setup font baker from temporary memory */ | |
11375 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { | |
11376 const struct nk_font_config *cfg = config_iter; | |
11377 if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0)) | |
11378 return nk_false; | |
11379 } | |
11380 | |
11381 *height = 0; | |
11382 *width = (total_glyph_count > 1000) ? 1024 : 512; | |
11383 nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); | |
11384 { | |
11385 int input_i = 0; | |
11386 int range_n = 0; | |
11387 int rect_n = 0; | |
11388 int char_n = 0; | |
11389 | |
11390 if (custom) { | |
11391 /* pack custom user data first so it will be in the upper left corner*/ | |
11392 struct nk_rp_rect custom_space; | |
11393 nk_zero(&custom_space, sizeof(custom_space)); | |
11394 custom_space.w = (nk_rp_coord)((custom->w * 2) + 1); | |
11395 custom_space.h = (nk_rp_coord)(custom->h + 1); | |
11396 | |
11397 nk_tt_PackSetOversampling(&baker->spc, 1, 1); | |
11398 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1); | |
11399 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); | |
11400 | |
11401 custom->x = (short)custom_space.x; | |
11402 custom->y = (short)custom_space.y; | |
11403 custom->w = (short)custom_space.w; | |
11404 custom->h = (short)custom_space.h; | |
11405 } | |
11406 | |
11407 /* first font pass: pack all glyphs */ | |
11408 for (input_i = 0, config_iter = config_list; input_i < count && config_iter; | |
11409 input_i++, config_iter = config_iter->next) | |
11410 { | |
11411 int n = 0; | |
11412 int glyph_count; | |
11413 const nk_rune *in_range; | |
11414 const struct nk_font_config *cfg = config_iter; | |
11415 struct nk_font_bake_data *tmp = &baker->build[input_i]; | |
11416 | |
11417 /* count glyphs + ranges in current font */ | |
11418 glyph_count = 0; range_count = 0; | |
11419 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { | |
11420 glyph_count += (int)(in_range[1] - in_range[0]) + 1; | |
11421 range_count++; | |
11422 } | |
11423 | |
11424 /* setup ranges */ | |
11425 tmp->ranges = baker->ranges + range_n; | |
11426 tmp->range_count = (nk_rune)range_count; | |
11427 range_n += range_count; | |
11428 for (i = 0; i < range_count; ++i) { | |
11429 in_range = &cfg->range[i * 2]; | |
11430 tmp->ranges[i].font_size = cfg->size; | |
11431 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; | |
11432 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; | |
11433 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; | |
11434 char_n += tmp->ranges[i].num_chars; | |
11435 } | |
11436 | |
11437 /* pack */ | |
11438 tmp->rects = baker->rects + rect_n; | |
11439 rect_n += glyph_count; | |
11440 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); | |
11441 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info, | |
11442 tmp->ranges, (int)tmp->range_count, tmp->rects); | |
11443 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n); | |
11444 | |
11445 /* texture height */ | |
11446 for (i = 0; i < n; ++i) { | |
11447 if (tmp->rects[i].was_packed) | |
11448 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); | |
11449 } | |
11450 } | |
11451 NK_ASSERT(rect_n == total_glyph_count); | |
11452 NK_ASSERT(char_n == total_glyph_count); | |
11453 NK_ASSERT(range_n == total_range_count); | |
11454 } | |
11455 *height = (int)nk_round_up_pow2((nk_uint)*height); | |
11456 *image_memory = (nk_size)(*width) * (nk_size)(*height); | |
11457 return nk_true; | |
11458 } | |
11459 | |
11460 NK_INTERN void | |
11461 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, | |
11462 struct nk_font_glyph *glyphs, int glyphs_count, | |
11463 const struct nk_font_config *config_list, int font_count) | |
11464 { | |
11465 int input_i = 0; | |
11466 nk_rune glyph_n = 0; | |
11467 const struct nk_font_config *config_iter; | |
11468 | |
11469 NK_ASSERT(image_memory); | |
11470 NK_ASSERT(width); | |
11471 NK_ASSERT(height); | |
11472 NK_ASSERT(config_list); | |
11473 NK_ASSERT(baker); | |
11474 NK_ASSERT(font_count); | |
11475 NK_ASSERT(glyphs_count); | |
11476 if (!image_memory || !width || !height || !config_list || | |
11477 !font_count || !glyphs || !glyphs_count) | |
11478 return; | |
11479 | |
11480 /* second font pass: render glyphs */ | |
11481 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); | |
11482 baker->spc.pixels = (unsigned char*)image_memory; | |
11483 baker->spc.height = (int)height; | |
11484 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; | |
11485 ++input_i, config_iter = config_iter->next) | |
11486 { | |
11487 const struct nk_font_config *cfg = config_iter; | |
11488 struct nk_font_bake_data *tmp = &baker->build[input_i]; | |
11489 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); | |
11490 nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, | |
11491 (int)tmp->range_count, tmp->rects, &baker->alloc); | |
11492 } | |
11493 nk_tt_PackEnd(&baker->spc, &baker->alloc); | |
11494 | |
11495 /* third pass: setup font and glyphs */ | |
11496 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; | |
11497 ++input_i, config_iter = config_iter->next) | |
11498 { | |
11499 nk_size i = 0; | |
11500 int char_idx = 0; | |
11501 nk_rune glyph_count = 0; | |
11502 const struct nk_font_config *cfg = config_iter; | |
11503 struct nk_font_bake_data *tmp = &baker->build[input_i]; | |
11504 struct nk_baked_font *dst_font = cfg->font; | |
11505 | |
11506 float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size); | |
11507 int unscaled_ascent, unscaled_descent, unscaled_line_gap; | |
11508 nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, | |
11509 &unscaled_line_gap); | |
11510 | |
11511 /* fill baked font */ | |
11512 if (!cfg->merge_mode) { | |
11513 dst_font->ranges = cfg->range; | |
11514 dst_font->height = cfg->size; | |
11515 dst_font->ascent = ((float)unscaled_ascent * font_scale); | |
11516 dst_font->descent = ((float)unscaled_descent * font_scale); | |
11517 dst_font->glyph_offset = glyph_n; | |
11518 } | |
11519 | |
11520 /* fill own baked font glyph array */ | |
11521 for (i = 0; i < tmp->range_count; ++i) | |
11522 { | |
11523 struct nk_tt_pack_range *range = &tmp->ranges[i]; | |
11524 for (char_idx = 0; char_idx < range->num_chars; char_idx++) | |
11525 { | |
11526 nk_rune codepoint = 0; | |
11527 float dummy_x = 0, dummy_y = 0; | |
11528 struct nk_tt_aligned_quad q; | |
11529 struct nk_font_glyph *glyph; | |
11530 | |
11531 /* query glyph bounds from stb_truetype */ | |
11532 const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx]; | |
11533 if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue; | |
11534 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); | |
11535 nk_tt_GetPackedQuad(range->chardata_for_range, (int)width, | |
11536 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); | |
11537 | |
11538 /* fill own glyph type with data */ | |
11539 glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count]; | |
11540 glyph->codepoint = codepoint; | |
11541 glyph->x0 = q.x0; glyph->y0 = q.y0; | |
11542 glyph->x1 = q.x1; glyph->y1 = q.y1; | |
11543 glyph->y0 += (dst_font->ascent + 0.5f); | |
11544 glyph->y1 += (dst_font->ascent + 0.5f); | |
11545 glyph->w = glyph->x1 - glyph->x0 + 0.5f; | |
11546 glyph->h = glyph->y1 - glyph->y0; | |
11547 | |
11548 if (cfg->coord_type == NK_COORD_PIXEL) { | |
11549 glyph->u0 = q.s0 * (float)width; | |
11550 glyph->v0 = q.t0 * (float)height; | |
11551 glyph->u1 = q.s1 * (float)width; | |
11552 glyph->v1 = q.t1 * (float)height; | |
11553 } else { | |
11554 glyph->u0 = q.s0; | |
11555 glyph->v0 = q.t0; | |
11556 glyph->u1 = q.s1; | |
11557 glyph->v1 = q.t1; | |
11558 } | |
11559 glyph->xadvance = (pc->xadvance + cfg->spacing.x); | |
11560 if (cfg->pixel_snap) | |
11561 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); | |
11562 glyph_count++; | |
11563 } | |
11564 } | |
11565 dst_font->glyph_count = glyph_count; | |
11566 glyph_n += dst_font->glyph_count; | |
11567 } | |
11568 } | |
11569 | |
11570 NK_INTERN void | |
11571 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, | |
11572 struct nk_recti img_dst, const char *texture_data_mask, int tex_width, | |
11573 int tex_height, char white, char black) | |
11574 { | |
11575 nk_byte *pixels; | |
11576 int y = 0; | |
11577 int x = 0; | |
11578 int n = 0; | |
11579 | |
11580 NK_ASSERT(img_memory); | |
11581 NK_ASSERT(img_width); | |
11582 NK_ASSERT(img_height); | |
11583 NK_ASSERT(texture_data_mask); | |
11584 NK_UNUSED(tex_height); | |
11585 if (!img_memory || !img_width || !img_height || !texture_data_mask) | |
11586 return; | |
11587 | |
11588 pixels = (nk_byte*)img_memory; | |
11589 for (y = 0, n = 0; y < tex_height; ++y) { | |
11590 for (x = 0; x < tex_width; ++x, ++n) { | |
11591 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); | |
11592 const int off1 = off0 + 1 + tex_width; | |
11593 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; | |
11594 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; | |
11595 } | |
11596 } | |
11597 } | |
11598 | |
11599 NK_INTERN void | |
11600 nk_font_bake_convert(void *out_memory, int img_width, int img_height, | |
11601 const void *in_memory) | |
11602 { | |
11603 int n = 0; | |
11604 nk_rune *dst; | |
11605 const nk_byte *src; | |
11606 | |
11607 NK_ASSERT(out_memory); | |
11608 NK_ASSERT(in_memory); | |
11609 NK_ASSERT(img_width); | |
11610 NK_ASSERT(img_height); | |
11611 if (!out_memory || !in_memory || !img_height || !img_width) return; | |
11612 | |
11613 dst = (nk_rune*)out_memory; | |
11614 src = (const nk_byte*)in_memory; | |
11615 for (n = (int)(img_width * img_height); n > 0; n--) | |
11616 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; | |
11617 } | |
11618 | |
11619 /* ------------------------------------------------------------- | |
11620 * | |
11621 * FONT | |
11622 * | |
11623 * --------------------------------------------------------------*/ | |
11624 NK_INTERN float | |
11625 nk_font_text_width(nk_handle handle, float height, const char *text, int len) | |
11626 { | |
11627 nk_rune unicode; | |
11628 int text_len = 0; | |
11629 float text_width = 0; | |
11630 int glyph_len = 0; | |
11631 float scale = 0; | |
11632 | |
11633 struct nk_font *font = (struct nk_font*)handle.ptr; | |
11634 NK_ASSERT(font); | |
11635 NK_ASSERT(font->glyphs); | |
11636 if (!font || !text || !len) | |
11637 return 0; | |
11638 | |
11639 scale = height/font->info.height; | |
11640 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); | |
11641 if (!glyph_len) return 0; | |
11642 while (text_len <= (int)len && glyph_len) { | |
11643 const struct nk_font_glyph *g; | |
11644 if (unicode == NK_UTF_INVALID) break; | |
11645 | |
11646 /* query currently drawn glyph information */ | |
11647 g = nk_font_find_glyph(font, unicode); | |
11648 text_width += g->xadvance * scale; | |
11649 | |
11650 /* offset next glyph */ | |
11651 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); | |
11652 text_len += glyph_len; | |
11653 } | |
11654 return text_width; | |
11655 } | |
11656 | |
11657 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
11658 NK_INTERN void | |
11659 nk_font_query_font_glyph(nk_handle handle, float height, | |
11660 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) | |
11661 { | |
11662 float scale; | |
11663 const struct nk_font_glyph *g; | |
11664 struct nk_font *font; | |
11665 | |
11666 NK_ASSERT(glyph); | |
11667 NK_UNUSED(next_codepoint); | |
11668 | |
11669 font = (struct nk_font*)handle.ptr; | |
11670 NK_ASSERT(font); | |
11671 NK_ASSERT(font->glyphs); | |
11672 if (!font || !glyph) | |
11673 return; | |
11674 | |
11675 scale = height/font->info.height; | |
11676 g = nk_font_find_glyph(font, codepoint); | |
11677 glyph->width = (g->x1 - g->x0) * scale; | |
11678 glyph->height = (g->y1 - g->y0) * scale; | |
11679 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); | |
11680 glyph->xadvance = (g->xadvance * scale); | |
11681 glyph->uv[0] = nk_vec2(g->u0, g->v0); | |
11682 glyph->uv[1] = nk_vec2(g->u1, g->v1); | |
11683 } | |
11684 #endif | |
11685 | |
11686 NK_API const struct nk_font_glyph* | |
11687 nk_font_find_glyph(struct nk_font *font, nk_rune unicode) | |
11688 { | |
11689 int i = 0; | |
11690 int count; | |
11691 int total_glyphs = 0; | |
11692 const struct nk_font_glyph *glyph = 0; | |
11693 | |
11694 NK_ASSERT(font); | |
11695 NK_ASSERT(font->glyphs); | |
11696 NK_ASSERT(font->info.ranges); | |
11697 if (!font || !font->glyphs) return 0; | |
11698 | |
11699 glyph = font->fallback; | |
11700 count = nk_range_count(font->info.ranges); | |
11701 for (i = 0; i < count; ++i) { | |
11702 nk_rune f = font->info.ranges[(i*2)+0]; | |
11703 nk_rune t = font->info.ranges[(i*2)+1]; | |
11704 int diff = (int)((t - f) + 1); | |
11705 if (unicode >= f && unicode <= t) | |
11706 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; | |
11707 total_glyphs += diff; | |
11708 } | |
11709 return glyph; | |
11710 } | |
11711 | |
11712 NK_INTERN void | |
11713 nk_font_init(struct nk_font *font, float pixel_height, | |
11714 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, | |
11715 const struct nk_baked_font *baked_font, nk_handle atlas) | |
11716 { | |
11717 struct nk_baked_font baked; | |
11718 NK_ASSERT(font); | |
11719 NK_ASSERT(glyphs); | |
11720 NK_ASSERT(baked_font); | |
11721 if (!font || !glyphs || !baked_font) | |
11722 return; | |
11723 | |
11724 baked = *baked_font; | |
11725 font->fallback = 0; | |
11726 font->info = baked; | |
11727 font->scale = (float)pixel_height / (float)font->info.height; | |
11728 font->glyphs = &glyphs[baked_font->glyph_offset]; | |
11729 font->texture = atlas; | |
11730 font->fallback_codepoint = fallback_codepoint; | |
11731 font->fallback = nk_font_find_glyph(font, fallback_codepoint); | |
11732 | |
11733 font->handle.height = font->info.height * font->scale; | |
11734 font->handle.width = nk_font_text_width; | |
11735 font->handle.userdata.ptr = font; | |
11736 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
11737 font->handle.query = nk_font_query_font_glyph; | |
11738 font->handle.texture = font->texture; | |
11739 #endif | |
11740 } | |
11741 | |
11742 /* --------------------------------------------------------------------------- | |
11743 * | |
11744 * DEFAULT FONT | |
11745 * | |
11746 * ProggyClean.ttf | |
11747 * Copyright (c) 2004, 2005 Tristan Grimmer | |
11748 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) | |
11749 * Download and more information at http://upperbounds.net | |
11750 *-----------------------------------------------------------------------------*/ | |
11751 #ifdef NK_INCLUDE_DEFAULT_FONT | |
11752 | |
11753 #ifdef __clang__ | |
11754 #pragma clang diagnostic push | |
11755 | |
11756 #pragma clang diagnostic ignored "-Woverlength-strings" | |
11757 #elif defined(__GNUC__) || defined(__GNUG__) | |
11758 #pragma GCC diagnostic push | |
11759 #pragma GCC diagnostic ignored "-Woverlength-strings" | |
11760 #endif | |
11761 | |
11762 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = | |
11763 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" | |
11764 "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#" | |
11765 "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL" | |
11766 "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N" | |
11767 "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N" | |
11768 "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cXm#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)" | |
11769 "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" | |
11770 "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." | |
11771 "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" | |
11772 "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(,)" | |
11773 "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#" | |
11774 "'/###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" | |
11775 "_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" | |
11776 "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/" | |
11777 "/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" | |
11778 "%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&#" | |
11779 "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)(" | |
11780 "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" | |
11781 "o;#2:;%d	v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" | |
11782 "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^-" | |
11783 "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-" | |
11784 "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" | |
11785 "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%" | |
11786 "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]" | |
11787 "%(?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" | |
11788 "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:" | |
11789 "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(" | |
11790 "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<" | |
11791 "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'?" | |
11792 "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/;" | |
11793 ")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" | |
11794 "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(" | |
11795 "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" | |
11796 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" | |
11797 "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<-" | |
11798 "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" | |
11799 "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P	r+$%CE=68>K8r0=dSC%%(@p7" | |
11800 ".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@@" | |
11801 "$&)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*" | |
11802 "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" | |
11803 "@-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&#" | |
11804 "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#" | |
11805 "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" | |
11806 "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" | |
11807 "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&#" | |
11808 "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" | |
11809 ":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+" | |
11810 "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*" | |
11811 "$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" | |
11812 ":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" | |
11813 "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" | |
11814 "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" | |
11815 "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" | |
11816 ":^#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@&]>" | |
11817 "_>@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%" | |
11818 "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;" | |
11819 "^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:" | |
11820 "+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%" | |
11821 "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-" | |
11822 "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*" | |
11823 "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" | |
11824 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-" | |
11825 "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`" | |
11826 "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]%/" | |
11827 "+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" | |
11828 "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" | |
11829 "?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" | |
11830 "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" | |
11831 ">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'>" | |
11832 "[%$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" | |
11833 "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#" | |
11834 "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$" | |
11835 "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,)" | |
11836 "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" | |
11837 "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" | |
11838 "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" | |
11839 "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(#" | |
11840 ";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&>" | |
11841 "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#" | |
11842 "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" | |
11843 "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#" | |
11844 "/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-#" | |
11845 "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#" | |
11846 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" | |
11847 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" | |
11848 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; | |
11849 #endif /* NK_INCLUDE_DEFAULT_FONT */ | |
11850 | |
11851 #define NK_CURSOR_DATA_W 90 | |
11852 #define NK_CURSOR_DATA_H 27 | |
11853 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = | |
11854 { | |
11855 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" | |
11856 "..- -X.....X- X.X - X.X -X.....X - X.....X" | |
11857 "--- -XXX.XXX- X...X - X...X -X....X - X....X" | |
11858 "X - X.X - X.....X - X.....X -X...X - X...X" | |
11859 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" | |
11860 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" | |
11861 "X..X - X.X - X.X - X.X -XX X.X - X.X XX" | |
11862 "X...X - X.X - X.X - XX X.X XX - X.X - X.X " | |
11863 "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " | |
11864 "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " | |
11865 "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " | |
11866 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " | |
11867 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " | |
11868 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " | |
11869 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " | |
11870 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " | |
11871 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " | |
11872 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" | |
11873 "X.X X..X - -X.......X- X.......X - XX XX - " | |
11874 "XX X..X - - X.....X - X.....X - X.X X.X - " | |
11875 " X..X - X...X - X...X - X..X X..X - " | |
11876 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " | |
11877 "------------ - X - X -X.....................X- " | |
11878 " ----------------------------------- X...XXXXXXXXXXXXX...X - " | |
11879 " - X..X X..X - " | |
11880 " - X.X X.X - " | |
11881 " - XX XX - " | |
11882 }; | |
11883 | |
11884 #ifdef __clang__ | |
11885 #pragma clang diagnostic pop | |
11886 #elif defined(__GNUC__) || defined(__GNUG__) | |
11887 #pragma GCC diagnostic pop | |
11888 #endif | |
11889 | |
11890 NK_INTERN unsigned int | |
11891 nk_decompress_length(unsigned char *input) | |
11892 { | |
11893 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); | |
11894 } | |
11895 | |
11896 NK_GLOBAL unsigned char *nk__barrier; | |
11897 NK_GLOBAL unsigned char *nk__barrier2; | |
11898 NK_GLOBAL unsigned char *nk__barrier3; | |
11899 NK_GLOBAL unsigned char *nk__barrier4; | |
11900 NK_GLOBAL unsigned char *nk__dout; | |
11901 | |
11902 NK_INTERN void | |
11903 nk__match(unsigned char *data, unsigned int length) | |
11904 { | |
11905 /* INVERSE of memmove... write each byte before copying the next...*/ | |
11906 NK_ASSERT (nk__dout + length <= nk__barrier); | |
11907 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } | |
11908 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } | |
11909 while (length--) *nk__dout++ = *data++; | |
11910 } | |
11911 | |
11912 NK_INTERN void | |
11913 nk__lit(unsigned char *data, unsigned int length) | |
11914 { | |
11915 NK_ASSERT (nk__dout + length <= nk__barrier); | |
11916 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } | |
11917 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } | |
11918 NK_MEMCPY(nk__dout, data, length); | |
11919 nk__dout += length; | |
11920 } | |
11921 | |
11922 #define nk__in2(x) ((i[x] << 8) + i[(x)+1]) | |
11923 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) | |
11924 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) | |
11925 | |
11926 NK_INTERN unsigned char* | |
11927 nk_decompress_token(unsigned char *i) | |
11928 { | |
11929 if (*i >= 0x20) { /* use fewer if's for cases that expand small */ | |
11930 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; | |
11931 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; | |
11932 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); | |
11933 } else { /* more ifs for cases that expand large, since overhead is amortized */ | |
11934 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; | |
11935 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; | |
11936 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); | |
11937 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); | |
11938 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; | |
11939 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; | |
11940 } | |
11941 return i; | |
11942 } | |
11943 | |
11944 NK_INTERN unsigned int | |
11945 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) | |
11946 { | |
11947 const unsigned long ADLER_MOD = 65521; | |
11948 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; | |
11949 unsigned long blocklen, i; | |
11950 | |
11951 blocklen = buflen % 5552; | |
11952 while (buflen) { | |
11953 for (i=0; i + 7 < blocklen; i += 8) { | |
11954 s1 += buffer[0]; s2 += s1; | |
11955 s1 += buffer[1]; s2 += s1; | |
11956 s1 += buffer[2]; s2 += s1; | |
11957 s1 += buffer[3]; s2 += s1; | |
11958 s1 += buffer[4]; s2 += s1; | |
11959 s1 += buffer[5]; s2 += s1; | |
11960 s1 += buffer[6]; s2 += s1; | |
11961 s1 += buffer[7]; s2 += s1; | |
11962 buffer += 8; | |
11963 } | |
11964 for (; i < blocklen; ++i) { | |
11965 s1 += *buffer++; s2 += s1; | |
11966 } | |
11967 | |
11968 s1 %= ADLER_MOD; s2 %= ADLER_MOD; | |
11969 buflen -= (unsigned int)blocklen; | |
11970 blocklen = 5552; | |
11971 } | |
11972 return (unsigned int)(s2 << 16) + (unsigned int)s1; | |
11973 } | |
11974 | |
11975 NK_INTERN unsigned int | |
11976 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) | |
11977 { | |
11978 unsigned int olen; | |
11979 if (nk__in4(0) != 0x57bC0000) return 0; | |
11980 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ | |
11981 olen = nk_decompress_length(i); | |
11982 nk__barrier2 = i; | |
11983 nk__barrier3 = i+length; | |
11984 nk__barrier = output + olen; | |
11985 nk__barrier4 = output; | |
11986 i += 16; | |
11987 | |
11988 nk__dout = output; | |
11989 for (;;) { | |
11990 unsigned char *old_i = i; | |
11991 i = nk_decompress_token(i); | |
11992 if (i == old_i) { | |
11993 if (*i == 0x05 && i[1] == 0xfa) { | |
11994 NK_ASSERT(nk__dout == output + olen); | |
11995 if (nk__dout != output + olen) return 0; | |
11996 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) | |
11997 return 0; | |
11998 return olen; | |
11999 } else { | |
12000 NK_ASSERT(0); /* NOTREACHED */ | |
12001 return 0; | |
12002 } | |
12003 } | |
12004 NK_ASSERT(nk__dout <= output + olen); | |
12005 if (nk__dout > output + olen) | |
12006 return 0; | |
12007 } | |
12008 } | |
12009 | |
12010 NK_INTERN unsigned int | |
12011 nk_decode_85_byte(char c) | |
12012 { return (unsigned int)((c >= '\\') ? c-36 : c-35); } | |
12013 | |
12014 NK_INTERN void | |
12015 nk_decode_85(unsigned char* dst, const unsigned char* src) | |
12016 { | |
12017 while (*src) | |
12018 { | |
12019 unsigned int tmp = | |
12020 nk_decode_85_byte((char)src[0]) + | |
12021 85 * (nk_decode_85_byte((char)src[1]) + | |
12022 85 * (nk_decode_85_byte((char)src[2]) + | |
12023 85 * (nk_decode_85_byte((char)src[3]) + | |
12024 85 * nk_decode_85_byte((char)src[4])))); | |
12025 | |
12026 /* we can't assume little-endianess. */ | |
12027 dst[0] = (unsigned char)((tmp >> 0) & 0xFF); | |
12028 dst[1] = (unsigned char)((tmp >> 8) & 0xFF); | |
12029 dst[2] = (unsigned char)((tmp >> 16) & 0xFF); | |
12030 dst[3] = (unsigned char)((tmp >> 24) & 0xFF); | |
12031 | |
12032 src += 5; | |
12033 dst += 4; | |
12034 } | |
12035 } | |
12036 | |
12037 /* ------------------------------------------------------------- | |
12038 * | |
12039 * FONT ATLAS | |
12040 * | |
12041 * --------------------------------------------------------------*/ | |
12042 NK_API struct nk_font_config | |
12043 nk_font_config(float pixel_height) | |
12044 { | |
12045 struct nk_font_config cfg; | |
12046 nk_zero_struct(cfg); | |
12047 cfg.ttf_blob = 0; | |
12048 cfg.ttf_size = 0; | |
12049 cfg.ttf_data_owned_by_atlas = 0; | |
12050 cfg.size = pixel_height; | |
12051 cfg.oversample_h = 3; | |
12052 cfg.oversample_v = 1; | |
12053 cfg.pixel_snap = 0; | |
12054 cfg.coord_type = NK_COORD_UV; | |
12055 cfg.spacing = nk_vec2(0,0); | |
12056 cfg.range = nk_font_default_glyph_ranges(); | |
12057 cfg.merge_mode = 0; | |
12058 cfg.fallback_glyph = '?'; | |
12059 cfg.font = 0; | |
12060 return cfg; | |
12061 } | |
12062 | |
12063 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
12064 NK_API void | |
12065 nk_font_atlas_init_default(struct nk_font_atlas *atlas) | |
12066 { | |
12067 NK_ASSERT(atlas); | |
12068 if (!atlas) return; | |
12069 nk_zero_struct(*atlas); | |
12070 atlas->temporary.userdata.ptr = 0; | |
12071 atlas->temporary.alloc = nk_malloc; | |
12072 atlas->temporary.free = nk_mfree; | |
12073 atlas->permanent.userdata.ptr = 0; | |
12074 atlas->permanent.alloc = nk_malloc; | |
12075 atlas->permanent.free = nk_mfree; | |
12076 } | |
12077 #endif | |
12078 | |
12079 NK_API void | |
12080 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) | |
12081 { | |
12082 NK_ASSERT(atlas); | |
12083 NK_ASSERT(alloc); | |
12084 if (!atlas || !alloc) return; | |
12085 nk_zero_struct(*atlas); | |
12086 atlas->permanent = *alloc; | |
12087 atlas->temporary = *alloc; | |
12088 } | |
12089 | |
12090 NK_API void | |
12091 nk_font_atlas_init_custom(struct nk_font_atlas *atlas, | |
12092 struct nk_allocator *permanent, struct nk_allocator *temporary) | |
12093 { | |
12094 NK_ASSERT(atlas); | |
12095 NK_ASSERT(permanent); | |
12096 NK_ASSERT(temporary); | |
12097 if (!atlas || !permanent || !temporary) return; | |
12098 nk_zero_struct(*atlas); | |
12099 atlas->permanent = *permanent; | |
12100 atlas->temporary = *temporary; | |
12101 } | |
12102 | |
12103 NK_API void | |
12104 nk_font_atlas_begin(struct nk_font_atlas *atlas) | |
12105 { | |
12106 NK_ASSERT(atlas); | |
12107 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); | |
12108 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); | |
12109 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || | |
12110 !atlas->temporary.alloc || !atlas->temporary.free) return; | |
12111 if (atlas->glyphs) { | |
12112 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); | |
12113 atlas->glyphs = 0; | |
12114 } | |
12115 if (atlas->pixel) { | |
12116 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); | |
12117 atlas->pixel = 0; | |
12118 } | |
12119 } | |
12120 | |
12121 NK_API struct nk_font* | |
12122 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) | |
12123 { | |
12124 struct nk_font *font = 0; | |
12125 struct nk_font_config *cfg; | |
12126 | |
12127 NK_ASSERT(atlas); | |
12128 NK_ASSERT(atlas->permanent.alloc); | |
12129 NK_ASSERT(atlas->permanent.free); | |
12130 NK_ASSERT(atlas->temporary.alloc); | |
12131 NK_ASSERT(atlas->temporary.free); | |
12132 | |
12133 NK_ASSERT(config); | |
12134 NK_ASSERT(config->ttf_blob); | |
12135 NK_ASSERT(config->ttf_size); | |
12136 NK_ASSERT(config->size > 0.0f); | |
12137 | |
12138 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| | |
12139 !atlas->permanent.alloc || !atlas->permanent.free || | |
12140 !atlas->temporary.alloc || !atlas->temporary.free) | |
12141 return 0; | |
12142 | |
12143 /* allocate and insert font config into list */ | |
12144 cfg = (struct nk_font_config*) | |
12145 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); | |
12146 NK_MEMCPY(cfg, config, sizeof(*config)); | |
12147 if (!atlas->config) { | |
12148 atlas->config = cfg; | |
12149 cfg->next = 0; | |
12150 } else { | |
12151 cfg->next = atlas->config; | |
12152 atlas->config = cfg; | |
12153 } | |
12154 | |
12155 /* allocate new font */ | |
12156 if (!config->merge_mode) { | |
12157 font = (struct nk_font*) | |
12158 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); | |
12159 NK_ASSERT(font); | |
12160 if (!font) return 0; | |
12161 font->config = cfg; | |
12162 } else { | |
12163 NK_ASSERT(atlas->font_num); | |
12164 font = atlas->fonts; | |
12165 font->config = cfg; | |
12166 } | |
12167 | |
12168 /* insert font into list */ | |
12169 if (!config->merge_mode) { | |
12170 if (!atlas->fonts) { | |
12171 atlas->fonts = font; | |
12172 font->next = 0; | |
12173 } else { | |
12174 font->next = atlas->fonts; | |
12175 atlas->fonts = font; | |
12176 } | |
12177 cfg->font = &font->info; | |
12178 } | |
12179 | |
12180 /* create own copy of .TTF font blob */ | |
12181 if (!config->ttf_data_owned_by_atlas) { | |
12182 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); | |
12183 NK_ASSERT(cfg->ttf_blob); | |
12184 if (!cfg->ttf_blob) { | |
12185 atlas->font_num++; | |
12186 return 0; | |
12187 } | |
12188 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); | |
12189 cfg->ttf_data_owned_by_atlas = 1; | |
12190 } | |
12191 atlas->font_num++; | |
12192 return font; | |
12193 } | |
12194 | |
12195 NK_API struct nk_font* | |
12196 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, | |
12197 nk_size size, float height, const struct nk_font_config *config) | |
12198 { | |
12199 struct nk_font_config cfg; | |
12200 NK_ASSERT(memory); | |
12201 NK_ASSERT(size); | |
12202 | |
12203 NK_ASSERT(atlas); | |
12204 NK_ASSERT(atlas->temporary.alloc); | |
12205 NK_ASSERT(atlas->temporary.free); | |
12206 NK_ASSERT(atlas->permanent.alloc); | |
12207 NK_ASSERT(atlas->permanent.free); | |
12208 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || | |
12209 !atlas->permanent.alloc || !atlas->permanent.free) | |
12210 return 0; | |
12211 | |
12212 cfg = (config) ? *config: nk_font_config(height); | |
12213 cfg.ttf_blob = memory; | |
12214 cfg.ttf_size = size; | |
12215 cfg.size = height; | |
12216 cfg.ttf_data_owned_by_atlas = 0; | |
12217 return nk_font_atlas_add(atlas, &cfg); | |
12218 } | |
12219 | |
12220 #ifdef NK_INCLUDE_STANDARD_IO | |
12221 NK_API struct nk_font* | |
12222 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, | |
12223 float height, const struct nk_font_config *config) | |
12224 { | |
12225 nk_size size; | |
12226 char *memory; | |
12227 struct nk_font_config cfg; | |
12228 | |
12229 NK_ASSERT(atlas); | |
12230 NK_ASSERT(atlas->temporary.alloc); | |
12231 NK_ASSERT(atlas->temporary.free); | |
12232 NK_ASSERT(atlas->permanent.alloc); | |
12233 NK_ASSERT(atlas->permanent.free); | |
12234 | |
12235 if (!atlas || !file_path) return 0; | |
12236 memory = nk_file_load(file_path, &size, &atlas->permanent); | |
12237 if (!memory) return 0; | |
12238 | |
12239 cfg = (config) ? *config: nk_font_config(height); | |
12240 cfg.ttf_blob = memory; | |
12241 cfg.ttf_size = size; | |
12242 cfg.size = height; | |
12243 cfg.ttf_data_owned_by_atlas = 1; | |
12244 return nk_font_atlas_add(atlas, &cfg); | |
12245 } | |
12246 #endif | |
12247 | |
12248 NK_API struct nk_font* | |
12249 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, | |
12250 void *compressed_data, nk_size compressed_size, float height, | |
12251 const struct nk_font_config *config) | |
12252 { | |
12253 unsigned int decompressed_size; | |
12254 void *decompressed_data; | |
12255 struct nk_font_config cfg; | |
12256 | |
12257 NK_ASSERT(atlas); | |
12258 NK_ASSERT(atlas->temporary.alloc); | |
12259 NK_ASSERT(atlas->temporary.free); | |
12260 NK_ASSERT(atlas->permanent.alloc); | |
12261 NK_ASSERT(atlas->permanent.free); | |
12262 | |
12263 NK_ASSERT(compressed_data); | |
12264 NK_ASSERT(compressed_size); | |
12265 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || | |
12266 !atlas->permanent.alloc || !atlas->permanent.free) | |
12267 return 0; | |
12268 | |
12269 decompressed_size = nk_decompress_length((unsigned char*)compressed_data); | |
12270 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); | |
12271 NK_ASSERT(decompressed_data); | |
12272 if (!decompressed_data) return 0; | |
12273 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, | |
12274 (unsigned int)compressed_size); | |
12275 | |
12276 cfg = (config) ? *config: nk_font_config(height); | |
12277 cfg.ttf_blob = decompressed_data; | |
12278 cfg.ttf_size = decompressed_size; | |
12279 cfg.size = height; | |
12280 cfg.ttf_data_owned_by_atlas = 1; | |
12281 return nk_font_atlas_add(atlas, &cfg); | |
12282 } | |
12283 | |
12284 NK_API struct nk_font* | |
12285 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, | |
12286 const char *data_base85, float height, const struct nk_font_config *config) | |
12287 { | |
12288 int compressed_size; | |
12289 void *compressed_data; | |
12290 struct nk_font *font; | |
12291 | |
12292 NK_ASSERT(atlas); | |
12293 NK_ASSERT(atlas->temporary.alloc); | |
12294 NK_ASSERT(atlas->temporary.free); | |
12295 NK_ASSERT(atlas->permanent.alloc); | |
12296 NK_ASSERT(atlas->permanent.free); | |
12297 | |
12298 NK_ASSERT(data_base85); | |
12299 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || | |
12300 !atlas->permanent.alloc || !atlas->permanent.free) | |
12301 return 0; | |
12302 | |
12303 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; | |
12304 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); | |
12305 NK_ASSERT(compressed_data); | |
12306 if (!compressed_data) return 0; | |
12307 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); | |
12308 font = nk_font_atlas_add_compressed(atlas, compressed_data, | |
12309 (nk_size)compressed_size, height, config); | |
12310 atlas->temporary.free(atlas->temporary.userdata, compressed_data); | |
12311 return font; | |
12312 } | |
12313 | |
12314 #ifdef NK_INCLUDE_DEFAULT_FONT | |
12315 NK_API struct nk_font* | |
12316 nk_font_atlas_add_default(struct nk_font_atlas *atlas, | |
12317 float pixel_height, const struct nk_font_config *config) | |
12318 { | |
12319 NK_ASSERT(atlas); | |
12320 NK_ASSERT(atlas->temporary.alloc); | |
12321 NK_ASSERT(atlas->temporary.free); | |
12322 NK_ASSERT(atlas->permanent.alloc); | |
12323 NK_ASSERT(atlas->permanent.free); | |
12324 return nk_font_atlas_add_compressed_base85(atlas, | |
12325 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); | |
12326 } | |
12327 #endif | |
12328 | |
12329 NK_API const void* | |
12330 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, | |
12331 enum nk_font_atlas_format fmt) | |
12332 { | |
12333 int i = 0; | |
12334 void *tmp = 0; | |
12335 nk_size tmp_size, img_size; | |
12336 struct nk_font *font_iter; | |
12337 struct nk_font_baker *baker; | |
12338 | |
12339 NK_ASSERT(atlas); | |
12340 NK_ASSERT(atlas->temporary.alloc); | |
12341 NK_ASSERT(atlas->temporary.free); | |
12342 NK_ASSERT(atlas->permanent.alloc); | |
12343 NK_ASSERT(atlas->permanent.free); | |
12344 | |
12345 NK_ASSERT(width); | |
12346 NK_ASSERT(height); | |
12347 if (!atlas || !width || !height || | |
12348 !atlas->temporary.alloc || !atlas->temporary.free || | |
12349 !atlas->permanent.alloc || !atlas->permanent.free) | |
12350 return 0; | |
12351 | |
12352 #ifdef NK_INCLUDE_DEFAULT_FONT | |
12353 /* no font added so just use default font */ | |
12354 if (!atlas->font_num) | |
12355 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); | |
12356 #endif | |
12357 NK_ASSERT(atlas->font_num); | |
12358 if (!atlas->font_num) return 0; | |
12359 | |
12360 /* allocate temporary baker memory required for the baking process */ | |
12361 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); | |
12362 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); | |
12363 NK_ASSERT(tmp); | |
12364 if (!tmp) goto failed; | |
12365 | |
12366 /* allocate glyph memory for all fonts */ | |
12367 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); | |
12368 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( | |
12369 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); | |
12370 NK_ASSERT(atlas->glyphs); | |
12371 if (!atlas->glyphs) | |
12372 goto failed; | |
12373 | |
12374 /* pack all glyphs into a tight fit space */ | |
12375 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; | |
12376 atlas->custom.h = NK_CURSOR_DATA_H + 1; | |
12377 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, | |
12378 atlas->config, atlas->font_num, &atlas->temporary)) | |
12379 goto failed; | |
12380 | |
12381 /* allocate memory for the baked image font atlas */ | |
12382 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); | |
12383 NK_ASSERT(atlas->pixel); | |
12384 if (!atlas->pixel) | |
12385 goto failed; | |
12386 | |
12387 /* bake glyphs and custom white pixel into image */ | |
12388 nk_font_bake(baker, atlas->pixel, *width, *height, | |
12389 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); | |
12390 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, | |
12391 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); | |
12392 | |
12393 if (fmt == NK_FONT_ATLAS_RGBA32) { | |
12394 /* convert alpha8 image into rgba32 image */ | |
12395 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, | |
12396 (nk_size)(*width * *height * 4)); | |
12397 NK_ASSERT(img_rgba); | |
12398 if (!img_rgba) goto failed; | |
12399 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); | |
12400 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); | |
12401 atlas->pixel = img_rgba; | |
12402 } | |
12403 atlas->tex_width = *width; | |
12404 atlas->tex_height = *height; | |
12405 | |
12406 /* initialize each font */ | |
12407 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { | |
12408 struct nk_font *font = font_iter; | |
12409 struct nk_font_config *config = font->config; | |
12410 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, | |
12411 config->font, nk_handle_ptr(0)); | |
12412 } | |
12413 | |
12414 /* initialize each cursor */ | |
12415 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { | |
12416 /* Pos ----- Size ------- Offset --*/ | |
12417 {{ 0, 3}, {12,19}, { 0, 0}}, | |
12418 {{13, 0}, { 7,16}, { 4, 8}}, | |
12419 {{31, 0}, {23,23}, {11,11}}, | |
12420 {{21, 0}, { 9, 23}, { 5,11}}, | |
12421 {{55,18}, {23, 9}, {11, 5}}, | |
12422 {{73, 0}, {17,17}, { 9, 9}}, | |
12423 {{55, 0}, {17,17}, { 9, 9}} | |
12424 }; | |
12425 for (i = 0; i < NK_CURSOR_COUNT; ++i) { | |
12426 struct nk_cursor *cursor = &atlas->cursors[i]; | |
12427 cursor->img.w = (unsigned short)*width; | |
12428 cursor->img.h = (unsigned short)*height; | |
12429 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); | |
12430 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); | |
12431 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; | |
12432 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; | |
12433 cursor->size = nk_cursor_data[i][1]; | |
12434 cursor->offset = nk_cursor_data[i][2]; | |
12435 }} | |
12436 /* free temporary memory */ | |
12437 atlas->temporary.free(atlas->temporary.userdata, tmp); | |
12438 return atlas->pixel; | |
12439 | |
12440 failed: | |
12441 /* error so cleanup all memory */ | |
12442 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); | |
12443 if (atlas->glyphs) { | |
12444 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); | |
12445 atlas->glyphs = 0; | |
12446 } | |
12447 if (atlas->pixel) { | |
12448 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); | |
12449 atlas->pixel = 0; | |
12450 } | |
12451 return 0; | |
12452 } | |
12453 | |
12454 NK_API void | |
12455 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, | |
12456 struct nk_draw_null_texture *null) | |
12457 { | |
12458 int i = 0; | |
12459 struct nk_font *font_iter; | |
12460 NK_ASSERT(atlas); | |
12461 if (!atlas) { | |
12462 if (!null) return; | |
12463 null->texture = texture; | |
12464 null->uv = nk_vec2(0.5f,0.5f); | |
12465 } | |
12466 if (null) { | |
12467 null->texture = texture; | |
12468 null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; | |
12469 null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; | |
12470 } | |
12471 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { | |
12472 font_iter->texture = texture; | |
12473 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
12474 font_iter->handle.texture = texture; | |
12475 #endif | |
12476 } | |
12477 for (i = 0; i < NK_CURSOR_COUNT; ++i) | |
12478 atlas->cursors[i].img.handle = texture; | |
12479 | |
12480 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); | |
12481 atlas->pixel = 0; | |
12482 atlas->tex_width = 0; | |
12483 atlas->tex_height = 0; | |
12484 atlas->custom.x = 0; | |
12485 atlas->custom.y = 0; | |
12486 atlas->custom.w = 0; | |
12487 atlas->custom.h = 0; | |
12488 } | |
12489 | |
12490 NK_API void | |
12491 nk_font_atlas_cleanup(struct nk_font_atlas *atlas) | |
12492 { | |
12493 NK_ASSERT(atlas); | |
12494 NK_ASSERT(atlas->temporary.alloc); | |
12495 NK_ASSERT(atlas->temporary.free); | |
12496 NK_ASSERT(atlas->permanent.alloc); | |
12497 NK_ASSERT(atlas->permanent.free); | |
12498 | |
12499 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; | |
12500 if (atlas->config) { | |
12501 struct nk_font_config *iter, *next; | |
12502 for (iter = atlas->config; iter; iter = next) { | |
12503 next = iter->next; | |
12504 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); | |
12505 atlas->permanent.free(atlas->permanent.userdata, iter); | |
12506 } | |
12507 atlas->config = 0; | |
12508 } | |
12509 } | |
12510 | |
12511 NK_API void | |
12512 nk_font_atlas_clear(struct nk_font_atlas *atlas) | |
12513 { | |
12514 NK_ASSERT(atlas); | |
12515 NK_ASSERT(atlas->temporary.alloc); | |
12516 NK_ASSERT(atlas->temporary.free); | |
12517 NK_ASSERT(atlas->permanent.alloc); | |
12518 NK_ASSERT(atlas->permanent.free); | |
12519 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; | |
12520 | |
12521 nk_font_atlas_cleanup(atlas); | |
12522 if (atlas->fonts) { | |
12523 struct nk_font *iter, *next; | |
12524 for (iter = atlas->fonts; iter; iter = next) { | |
12525 next = iter->next; | |
12526 atlas->permanent.free(atlas->permanent.userdata, iter); | |
12527 } | |
12528 atlas->fonts = 0; | |
12529 } | |
12530 if (atlas->glyphs) | |
12531 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); | |
12532 nk_zero_struct(*atlas); | |
12533 } | |
12534 #endif | |
12535 /* ============================================================== | |
12536 * | |
12537 * INPUT | |
12538 * | |
12539 * ===============================================================*/ | |
12540 NK_API void | |
12541 nk_input_begin(struct nk_context *ctx) | |
12542 { | |
12543 int i; | |
12544 struct nk_input *in; | |
12545 NK_ASSERT(ctx); | |
12546 if (!ctx) return; | |
12547 in = &ctx->input; | |
12548 for (i = 0; i < NK_BUTTON_MAX; ++i) | |
12549 in->mouse.buttons[i].clicked = 0; | |
12550 | |
12551 in->keyboard.text_len = 0; | |
12552 in->mouse.scroll_delta = nk_vec2(0,0); | |
12553 in->mouse.prev.x = in->mouse.pos.x; | |
12554 in->mouse.prev.y = in->mouse.pos.y; | |
12555 in->mouse.delta.x = 0; | |
12556 in->mouse.delta.y = 0; | |
12557 for (i = 0; i < NK_KEY_MAX; i++) | |
12558 in->keyboard.keys[i].clicked = 0; | |
12559 } | |
12560 | |
12561 NK_API void | |
12562 nk_input_end(struct nk_context *ctx) | |
12563 { | |
12564 struct nk_input *in; | |
12565 NK_ASSERT(ctx); | |
12566 if (!ctx) return; | |
12567 in = &ctx->input; | |
12568 if (in->mouse.grab) | |
12569 in->mouse.grab = 0; | |
12570 if (in->mouse.ungrab) { | |
12571 in->mouse.grabbed = 0; | |
12572 in->mouse.ungrab = 0; | |
12573 in->mouse.grab = 0; | |
12574 } | |
12575 } | |
12576 | |
12577 NK_API void | |
12578 nk_input_motion(struct nk_context *ctx, int x, int y) | |
12579 { | |
12580 struct nk_input *in; | |
12581 NK_ASSERT(ctx); | |
12582 if (!ctx) return; | |
12583 in = &ctx->input; | |
12584 in->mouse.pos.x = (float)x; | |
12585 in->mouse.pos.y = (float)y; | |
12586 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; | |
12587 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; | |
12588 } | |
12589 | |
12590 NK_API void | |
12591 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) | |
12592 { | |
12593 struct nk_input *in; | |
12594 NK_ASSERT(ctx); | |
12595 if (!ctx) return; | |
12596 in = &ctx->input; | |
12597 if (in->keyboard.keys[key].down != down) | |
12598 in->keyboard.keys[key].clicked++; | |
12599 in->keyboard.keys[key].down = down; | |
12600 } | |
12601 | |
12602 NK_API void | |
12603 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down) | |
12604 { | |
12605 struct nk_mouse_button *btn; | |
12606 struct nk_input *in; | |
12607 NK_ASSERT(ctx); | |
12608 if (!ctx) return; | |
12609 in = &ctx->input; | |
12610 if (in->mouse.buttons[id].down == down) return; | |
12611 | |
12612 btn = &in->mouse.buttons[id]; | |
12613 btn->clicked_pos.x = (float)x; | |
12614 btn->clicked_pos.y = (float)y; | |
12615 btn->down = down; | |
12616 btn->clicked++; | |
12617 } | |
12618 | |
12619 NK_API void | |
12620 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val) | |
12621 { | |
12622 NK_ASSERT(ctx); | |
12623 if (!ctx) return; | |
12624 ctx->input.mouse.scroll_delta.x += val.x; | |
12625 ctx->input.mouse.scroll_delta.y += val.y; | |
12626 } | |
12627 | |
12628 NK_API void | |
12629 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) | |
12630 { | |
12631 int len = 0; | |
12632 nk_rune unicode; | |
12633 struct nk_input *in; | |
12634 | |
12635 NK_ASSERT(ctx); | |
12636 if (!ctx) return; | |
12637 in = &ctx->input; | |
12638 | |
12639 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); | |
12640 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { | |
12641 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], | |
12642 NK_INPUT_MAX - in->keyboard.text_len); | |
12643 in->keyboard.text_len += len; | |
12644 } | |
12645 } | |
12646 | |
12647 NK_API void | |
12648 nk_input_char(struct nk_context *ctx, char c) | |
12649 { | |
12650 nk_glyph glyph; | |
12651 NK_ASSERT(ctx); | |
12652 if (!ctx) return; | |
12653 glyph[0] = c; | |
12654 nk_input_glyph(ctx, glyph); | |
12655 } | |
12656 | |
12657 NK_API void | |
12658 nk_input_unicode(struct nk_context *ctx, nk_rune unicode) | |
12659 { | |
12660 nk_glyph rune; | |
12661 NK_ASSERT(ctx); | |
12662 if (!ctx) return; | |
12663 nk_utf_encode(unicode, rune, NK_UTF_SIZE); | |
12664 nk_input_glyph(ctx, rune); | |
12665 } | |
12666 | |
12667 NK_API int | |
12668 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) | |
12669 { | |
12670 const struct nk_mouse_button *btn; | |
12671 if (!i) return nk_false; | |
12672 btn = &i->mouse.buttons[id]; | |
12673 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; | |
12674 } | |
12675 | |
12676 NK_API int | |
12677 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, | |
12678 struct nk_rect b) | |
12679 { | |
12680 const struct nk_mouse_button *btn; | |
12681 if (!i) return nk_false; | |
12682 btn = &i->mouse.buttons[id]; | |
12683 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) | |
12684 return nk_false; | |
12685 return nk_true; | |
12686 } | |
12687 | |
12688 NK_API int | |
12689 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, | |
12690 struct nk_rect b, int down) | |
12691 { | |
12692 const struct nk_mouse_button *btn; | |
12693 if (!i) return nk_false; | |
12694 btn = &i->mouse.buttons[id]; | |
12695 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); | |
12696 } | |
12697 | |
12698 NK_API int | |
12699 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, | |
12700 struct nk_rect b) | |
12701 { | |
12702 const struct nk_mouse_button *btn; | |
12703 if (!i) return nk_false; | |
12704 btn = &i->mouse.buttons[id]; | |
12705 return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && | |
12706 btn->clicked) ? nk_true : nk_false; | |
12707 } | |
12708 | |
12709 NK_API int | |
12710 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, | |
12711 struct nk_rect b, int down) | |
12712 { | |
12713 const struct nk_mouse_button *btn; | |
12714 if (!i) return nk_false; | |
12715 btn = &i->mouse.buttons[id]; | |
12716 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && | |
12717 btn->clicked) ? nk_true : nk_false; | |
12718 } | |
12719 | |
12720 NK_API int | |
12721 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) | |
12722 { | |
12723 int i, down = 0; | |
12724 for (i = 0; i < NK_BUTTON_MAX; ++i) | |
12725 down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); | |
12726 return down; | |
12727 } | |
12728 | |
12729 NK_API int | |
12730 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) | |
12731 { | |
12732 if (!i) return nk_false; | |
12733 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); | |
12734 } | |
12735 | |
12736 NK_API int | |
12737 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) | |
12738 { | |
12739 if (!i) return nk_false; | |
12740 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); | |
12741 } | |
12742 | |
12743 NK_API int | |
12744 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) | |
12745 { | |
12746 if (!i) return nk_false; | |
12747 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; | |
12748 return nk_input_is_mouse_click_in_rect(i, id, rect); | |
12749 } | |
12750 | |
12751 NK_API int | |
12752 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) | |
12753 { | |
12754 if (!i) return nk_false; | |
12755 return i->mouse.buttons[id].down; | |
12756 } | |
12757 | |
12758 NK_API int | |
12759 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) | |
12760 { | |
12761 const struct nk_mouse_button *b; | |
12762 if (!i) return nk_false; | |
12763 b = &i->mouse.buttons[id]; | |
12764 if (b->down && b->clicked) | |
12765 return nk_true; | |
12766 return nk_false; | |
12767 } | |
12768 | |
12769 NK_API int | |
12770 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) | |
12771 { | |
12772 if (!i) return nk_false; | |
12773 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); | |
12774 } | |
12775 | |
12776 NK_API int | |
12777 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) | |
12778 { | |
12779 const struct nk_key *k; | |
12780 if (!i) return nk_false; | |
12781 k = &i->keyboard.keys[key]; | |
12782 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) | |
12783 return nk_true; | |
12784 return nk_false; | |
12785 } | |
12786 | |
12787 NK_API int | |
12788 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) | |
12789 { | |
12790 const struct nk_key *k; | |
12791 if (!i) return nk_false; | |
12792 k = &i->keyboard.keys[key]; | |
12793 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) | |
12794 return nk_true; | |
12795 return nk_false; | |
12796 } | |
12797 | |
12798 NK_API int | |
12799 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) | |
12800 { | |
12801 const struct nk_key *k; | |
12802 if (!i) return nk_false; | |
12803 k = &i->keyboard.keys[key]; | |
12804 if (k->down) return nk_true; | |
12805 return nk_false; | |
12806 } | |
12807 | |
12808 /* | |
12809 * ============================================================== | |
12810 * | |
12811 * TEXT EDITOR | |
12812 * | |
12813 * =============================================================== | |
12814 */ | |
12815 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */ | |
12816 struct nk_text_find { | |
12817 float x,y; /* position of n'th character */ | |
12818 float height; /* height of line */ | |
12819 int first_char, length; /* first char of row, and length */ | |
12820 int prev_first; /*_ first char of previous row */ | |
12821 }; | |
12822 | |
12823 struct nk_text_edit_row { | |
12824 float x0,x1; | |
12825 /* starting x location, end x location (allows for align=right, etc) */ | |
12826 float baseline_y_delta; | |
12827 /* position of baseline relative to previous row's baseline*/ | |
12828 float ymin,ymax; | |
12829 /* height of row above and below baseline */ | |
12830 int num_chars; | |
12831 }; | |
12832 | |
12833 /* forward declarations */ | |
12834 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); | |
12835 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); | |
12836 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); | |
12837 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) | |
12838 | |
12839 NK_INTERN float | |
12840 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, | |
12841 const struct nk_user_font *font) | |
12842 { | |
12843 int len = 0; | |
12844 nk_rune unicode = 0; | |
12845 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); | |
12846 return font->width(font->userdata, font->height, str, len); | |
12847 } | |
12848 | |
12849 NK_INTERN void | |
12850 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, | |
12851 int line_start_id, float row_height, const struct nk_user_font *font) | |
12852 { | |
12853 int l; | |
12854 int glyphs = 0; | |
12855 nk_rune unicode; | |
12856 const char *remaining; | |
12857 int len = nk_str_len_char(&edit->string); | |
12858 const char *end = nk_str_get_const(&edit->string) + len; | |
12859 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); | |
12860 const struct nk_vec2 size = nk_text_calculate_text_bounds(font, | |
12861 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); | |
12862 | |
12863 r->x0 = 0.0f; | |
12864 r->x1 = size.x; | |
12865 r->baseline_y_delta = size.y; | |
12866 r->ymin = 0.0f; | |
12867 r->ymax = size.y; | |
12868 r->num_chars = glyphs; | |
12869 } | |
12870 | |
12871 NK_INTERN int | |
12872 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, | |
12873 const struct nk_user_font *font, float row_height) | |
12874 { | |
12875 struct nk_text_edit_row r; | |
12876 int n = edit->string.len; | |
12877 float base_y = 0, prev_x; | |
12878 int i=0, k; | |
12879 | |
12880 r.x0 = r.x1 = 0; | |
12881 r.ymin = r.ymax = 0; | |
12882 r.num_chars = 0; | |
12883 | |
12884 /* search rows to find one that straddles 'y' */ | |
12885 while (i < n) { | |
12886 nk_textedit_layout_row(&r, edit, i, row_height, font); | |
12887 if (r.num_chars <= 0) | |
12888 return n; | |
12889 | |
12890 if (i==0 && y < base_y + r.ymin) | |
12891 return 0; | |
12892 | |
12893 if (y < base_y + r.ymax) | |
12894 break; | |
12895 | |
12896 i += r.num_chars; | |
12897 base_y += r.baseline_y_delta; | |
12898 } | |
12899 | |
12900 /* below all text, return 'after' last character */ | |
12901 if (i >= n) | |
12902 return n; | |
12903 | |
12904 /* check if it's before the beginning of the line */ | |
12905 if (x < r.x0) | |
12906 return i; | |
12907 | |
12908 /* check if it's before the end of the line */ | |
12909 if (x < r.x1) { | |
12910 /* search characters in row for one that straddles 'x' */ | |
12911 k = i; | |
12912 prev_x = r.x0; | |
12913 for (i=0; i < r.num_chars; ++i) { | |
12914 float w = nk_textedit_get_width(edit, k, i, font); | |
12915 if (x < prev_x+w) { | |
12916 if (x < prev_x+w/2) | |
12917 return k+i; | |
12918 else return k+i+1; | |
12919 } | |
12920 prev_x += w; | |
12921 } | |
12922 /* shouldn't happen, but if it does, fall through to end-of-line case */ | |
12923 } | |
12924 | |
12925 /* if the last character is a newline, return that. | |
12926 * otherwise return 'after' the last character */ | |
12927 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') | |
12928 return i+r.num_chars-1; | |
12929 else return i+r.num_chars; | |
12930 } | |
12931 | |
12932 NK_INTERN void | |
12933 nk_textedit_click(struct nk_text_edit *state, float x, float y, | |
12934 const struct nk_user_font *font, float row_height) | |
12935 { | |
12936 /* API click: on mouse down, move the cursor to the clicked location, | |
12937 * and reset the selection */ | |
12938 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); | |
12939 state->select_start = state->cursor; | |
12940 state->select_end = state->cursor; | |
12941 state->has_preferred_x = 0; | |
12942 } | |
12943 | |
12944 NK_INTERN void | |
12945 nk_textedit_drag(struct nk_text_edit *state, float x, float y, | |
12946 const struct nk_user_font *font, float row_height) | |
12947 { | |
12948 /* API drag: on mouse drag, move the cursor and selection endpoint | |
12949 * to the clicked location */ | |
12950 int p = nk_textedit_locate_coord(state, x, y, font, row_height); | |
12951 if (state->select_start == state->select_end) | |
12952 state->select_start = state->cursor; | |
12953 state->cursor = state->select_end = p; | |
12954 } | |
12955 | |
12956 NK_INTERN void | |
12957 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, | |
12958 int n, int single_line, const struct nk_user_font *font, float row_height) | |
12959 { | |
12960 /* find the x/y location of a character, and remember info about the previous | |
12961 * row in case we get a move-up event (for page up, we'll have to rescan) */ | |
12962 struct nk_text_edit_row r; | |
12963 int prev_start = 0; | |
12964 int z = state->string.len; | |
12965 int i=0, first; | |
12966 | |
12967 nk_zero_struct(r); | |
12968 if (n == z) { | |
12969 /* if it's at the end, then find the last line -- simpler than trying to | |
12970 explicitly handle this case in the regular code */ | |
12971 nk_textedit_layout_row(&r, state, 0, row_height, font); | |
12972 if (single_line) { | |
12973 find->first_char = 0; | |
12974 find->length = z; | |
12975 } else { | |
12976 while (i < z) { | |
12977 prev_start = i; | |
12978 i += r.num_chars; | |
12979 nk_textedit_layout_row(&r, state, i, row_height, font); | |
12980 } | |
12981 | |
12982 find->first_char = i; | |
12983 find->length = r.num_chars; | |
12984 } | |
12985 find->x = r.x1; | |
12986 find->y = r.ymin; | |
12987 find->height = r.ymax - r.ymin; | |
12988 find->prev_first = prev_start; | |
12989 return; | |
12990 } | |
12991 | |
12992 /* search rows to find the one that straddles character n */ | |
12993 find->y = 0; | |
12994 | |
12995 for(;;) { | |
12996 nk_textedit_layout_row(&r, state, i, row_height, font); | |
12997 if (n < i + r.num_chars) break; | |
12998 prev_start = i; | |
12999 i += r.num_chars; | |
13000 find->y += r.baseline_y_delta; | |
13001 } | |
13002 | |
13003 find->first_char = first = i; | |
13004 find->length = r.num_chars; | |
13005 find->height = r.ymax - r.ymin; | |
13006 find->prev_first = prev_start; | |
13007 | |
13008 /* now scan to find xpos */ | |
13009 find->x = r.x0; | |
13010 for (i=0; first+i < n; ++i) | |
13011 find->x += nk_textedit_get_width(state, first, i, font); | |
13012 } | |
13013 | |
13014 NK_INTERN void | |
13015 nk_textedit_clamp(struct nk_text_edit *state) | |
13016 { | |
13017 /* make the selection/cursor state valid if client altered the string */ | |
13018 int n = state->string.len; | |
13019 if (NK_TEXT_HAS_SELECTION(state)) { | |
13020 if (state->select_start > n) state->select_start = n; | |
13021 if (state->select_end > n) state->select_end = n; | |
13022 /* if clamping forced them to be equal, move the cursor to match */ | |
13023 if (state->select_start == state->select_end) | |
13024 state->cursor = state->select_start; | |
13025 } | |
13026 if (state->cursor > n) state->cursor = n; | |
13027 } | |
13028 | |
13029 NK_API void | |
13030 nk_textedit_delete(struct nk_text_edit *state, int where, int len) | |
13031 { | |
13032 /* delete characters while updating undo */ | |
13033 nk_textedit_makeundo_delete(state, where, len); | |
13034 nk_str_delete_runes(&state->string, where, len); | |
13035 state->has_preferred_x = 0; | |
13036 } | |
13037 | |
13038 NK_API void | |
13039 nk_textedit_delete_selection(struct nk_text_edit *state) | |
13040 { | |
13041 /* delete the section */ | |
13042 nk_textedit_clamp(state); | |
13043 if (NK_TEXT_HAS_SELECTION(state)) { | |
13044 if (state->select_start < state->select_end) { | |
13045 nk_textedit_delete(state, state->select_start, | |
13046 state->select_end - state->select_start); | |
13047 state->select_end = state->cursor = state->select_start; | |
13048 } else { | |
13049 nk_textedit_delete(state, state->select_end, | |
13050 state->select_start - state->select_end); | |
13051 state->select_start = state->cursor = state->select_end; | |
13052 } | |
13053 state->has_preferred_x = 0; | |
13054 } | |
13055 } | |
13056 | |
13057 NK_INTERN void | |
13058 nk_textedit_sortselection(struct nk_text_edit *state) | |
13059 { | |
13060 /* canonicalize the selection so start <= end */ | |
13061 if (state->select_end < state->select_start) { | |
13062 int temp = state->select_end; | |
13063 state->select_end = state->select_start; | |
13064 state->select_start = temp; | |
13065 } | |
13066 } | |
13067 | |
13068 NK_INTERN void | |
13069 nk_textedit_move_to_first(struct nk_text_edit *state) | |
13070 { | |
13071 /* move cursor to first character of selection */ | |
13072 if (NK_TEXT_HAS_SELECTION(state)) { | |
13073 nk_textedit_sortselection(state); | |
13074 state->cursor = state->select_start; | |
13075 state->select_end = state->select_start; | |
13076 state->has_preferred_x = 0; | |
13077 } | |
13078 } | |
13079 | |
13080 NK_INTERN void | |
13081 nk_textedit_move_to_last(struct nk_text_edit *state) | |
13082 { | |
13083 /* move cursor to last character of selection */ | |
13084 if (NK_TEXT_HAS_SELECTION(state)) { | |
13085 nk_textedit_sortselection(state); | |
13086 nk_textedit_clamp(state); | |
13087 state->cursor = state->select_end; | |
13088 state->select_start = state->select_end; | |
13089 state->has_preferred_x = 0; | |
13090 } | |
13091 } | |
13092 | |
13093 NK_INTERN int | |
13094 nk_is_word_boundary( struct nk_text_edit *state, int idx) | |
13095 { | |
13096 int len; | |
13097 nk_rune c; | |
13098 if (idx <= 0) return 1; | |
13099 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; | |
13100 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || | |
13101 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || | |
13102 c == '|'); | |
13103 } | |
13104 | |
13105 NK_INTERN int | |
13106 nk_textedit_move_to_word_previous(struct nk_text_edit *state) | |
13107 { | |
13108 int c = state->cursor - 1; | |
13109 while( c >= 0 && !nk_is_word_boundary(state, c)) | |
13110 --c; | |
13111 | |
13112 if( c < 0 ) | |
13113 c = 0; | |
13114 | |
13115 return c; | |
13116 } | |
13117 | |
13118 NK_INTERN int | |
13119 nk_textedit_move_to_word_next(struct nk_text_edit *state) | |
13120 { | |
13121 const int len = state->string.len; | |
13122 int c = state->cursor+1; | |
13123 while( c < len && !nk_is_word_boundary(state, c)) | |
13124 ++c; | |
13125 | |
13126 if( c > len ) | |
13127 c = len; | |
13128 | |
13129 return c; | |
13130 } | |
13131 | |
13132 NK_INTERN void | |
13133 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) | |
13134 { | |
13135 /* update selection and cursor to match each other */ | |
13136 if (!NK_TEXT_HAS_SELECTION(state)) | |
13137 state->select_start = state->select_end = state->cursor; | |
13138 else state->cursor = state->select_end; | |
13139 } | |
13140 | |
13141 NK_API int | |
13142 nk_textedit_cut(struct nk_text_edit *state) | |
13143 { | |
13144 /* API cut: delete selection */ | |
13145 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) | |
13146 return 0; | |
13147 if (NK_TEXT_HAS_SELECTION(state)) { | |
13148 nk_textedit_delete_selection(state); /* implicitly clamps */ | |
13149 state->has_preferred_x = 0; | |
13150 return 1; | |
13151 } | |
13152 return 0; | |
13153 } | |
13154 | |
13155 NK_API int | |
13156 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) | |
13157 { | |
13158 /* API paste: replace existing selection with passed-in text */ | |
13159 int glyphs; | |
13160 const char *text = (const char *) ctext; | |
13161 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; | |
13162 | |
13163 /* if there's a selection, the paste should delete it */ | |
13164 nk_textedit_clamp(state); | |
13165 nk_textedit_delete_selection(state); | |
13166 | |
13167 /* try to insert the characters */ | |
13168 glyphs = nk_utf_len(ctext, len); | |
13169 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { | |
13170 nk_textedit_makeundo_insert(state, state->cursor, glyphs); | |
13171 state->cursor += len; | |
13172 state->has_preferred_x = 0; | |
13173 return 1; | |
13174 } | |
13175 /* remove the undo since we didn't actually insert the characters */ | |
13176 if (state->undo.undo_point) | |
13177 --state->undo.undo_point; | |
13178 return 0; | |
13179 } | |
13180 | |
13181 NK_API void | |
13182 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) | |
13183 { | |
13184 nk_rune unicode; | |
13185 int glyph_len; | |
13186 int text_len = 0; | |
13187 | |
13188 NK_ASSERT(state); | |
13189 NK_ASSERT(text); | |
13190 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; | |
13191 | |
13192 glyph_len = nk_utf_decode(text, &unicode, total_len); | |
13193 while ((text_len < total_len) && glyph_len) | |
13194 { | |
13195 /* don't insert a backward delete, just process the event */ | |
13196 if (unicode == 127) goto next; | |
13197 /* can't add newline in single-line mode */ | |
13198 if (unicode == '\n' && state->single_line) goto next; | |
13199 /* filter incoming text */ | |
13200 if (state->filter && !state->filter(state, unicode)) goto next; | |
13201 | |
13202 if (!NK_TEXT_HAS_SELECTION(state) && | |
13203 state->cursor < state->string.len) | |
13204 { | |
13205 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { | |
13206 nk_textedit_makeundo_replace(state, state->cursor, 1, 1); | |
13207 nk_str_delete_runes(&state->string, state->cursor, 1); | |
13208 } | |
13209 if (nk_str_insert_text_utf8(&state->string, state->cursor, | |
13210 text+text_len, 1)) | |
13211 { | |
13212 ++state->cursor; | |
13213 state->has_preferred_x = 0; | |
13214 } | |
13215 } else { | |
13216 nk_textedit_delete_selection(state); /* implicitly clamps */ | |
13217 if (nk_str_insert_text_utf8(&state->string, state->cursor, | |
13218 text+text_len, 1)) | |
13219 { | |
13220 nk_textedit_makeundo_insert(state, state->cursor, 1); | |
13221 ++state->cursor; | |
13222 state->has_preferred_x = 0; | |
13223 } | |
13224 } | |
13225 next: | |
13226 text_len += glyph_len; | |
13227 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); | |
13228 } | |
13229 } | |
13230 | |
13231 NK_INTERN void | |
13232 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, | |
13233 const struct nk_user_font *font, float row_height) | |
13234 { | |
13235 retry: | |
13236 switch (key) | |
13237 { | |
13238 case NK_KEY_NONE: | |
13239 case NK_KEY_CTRL: | |
13240 case NK_KEY_ENTER: | |
13241 case NK_KEY_SHIFT: | |
13242 case NK_KEY_TAB: | |
13243 case NK_KEY_COPY: | |
13244 case NK_KEY_CUT: | |
13245 case NK_KEY_PASTE: | |
13246 case NK_KEY_MAX: | |
13247 default: break; | |
13248 case NK_KEY_TEXT_UNDO: | |
13249 nk_textedit_undo(state); | |
13250 state->has_preferred_x = 0; | |
13251 break; | |
13252 | |
13253 case NK_KEY_TEXT_REDO: | |
13254 nk_textedit_redo(state); | |
13255 state->has_preferred_x = 0; | |
13256 break; | |
13257 | |
13258 case NK_KEY_TEXT_SELECT_ALL: | |
13259 nk_textedit_select_all(state); | |
13260 state->has_preferred_x = 0; | |
13261 break; | |
13262 | |
13263 case NK_KEY_TEXT_INSERT_MODE: | |
13264 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) | |
13265 state->mode = NK_TEXT_EDIT_MODE_INSERT; | |
13266 break; | |
13267 case NK_KEY_TEXT_REPLACE_MODE: | |
13268 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) | |
13269 state->mode = NK_TEXT_EDIT_MODE_REPLACE; | |
13270 break; | |
13271 case NK_KEY_TEXT_RESET_MODE: | |
13272 if (state->mode == NK_TEXT_EDIT_MODE_INSERT || | |
13273 state->mode == NK_TEXT_EDIT_MODE_REPLACE) | |
13274 state->mode = NK_TEXT_EDIT_MODE_VIEW; | |
13275 break; | |
13276 | |
13277 case NK_KEY_LEFT: | |
13278 if (shift_mod) { | |
13279 nk_textedit_clamp(state); | |
13280 nk_textedit_prep_selection_at_cursor(state); | |
13281 /* move selection left */ | |
13282 if (state->select_end > 0) | |
13283 --state->select_end; | |
13284 state->cursor = state->select_end; | |
13285 state->has_preferred_x = 0; | |
13286 } else { | |
13287 /* if currently there's a selection, | |
13288 * move cursor to start of selection */ | |
13289 if (NK_TEXT_HAS_SELECTION(state)) | |
13290 nk_textedit_move_to_first(state); | |
13291 else if (state->cursor > 0) | |
13292 --state->cursor; | |
13293 state->has_preferred_x = 0; | |
13294 } break; | |
13295 | |
13296 case NK_KEY_RIGHT: | |
13297 if (shift_mod) { | |
13298 nk_textedit_prep_selection_at_cursor(state); | |
13299 /* move selection right */ | |
13300 ++state->select_end; | |
13301 nk_textedit_clamp(state); | |
13302 state->cursor = state->select_end; | |
13303 state->has_preferred_x = 0; | |
13304 } else { | |
13305 /* if currently there's a selection, | |
13306 * move cursor to end of selection */ | |
13307 if (NK_TEXT_HAS_SELECTION(state)) | |
13308 nk_textedit_move_to_last(state); | |
13309 else ++state->cursor; | |
13310 nk_textedit_clamp(state); | |
13311 state->has_preferred_x = 0; | |
13312 } break; | |
13313 | |
13314 case NK_KEY_TEXT_WORD_LEFT: | |
13315 if (shift_mod) { | |
13316 if( !NK_TEXT_HAS_SELECTION( state ) ) | |
13317 nk_textedit_prep_selection_at_cursor(state); | |
13318 state->cursor = nk_textedit_move_to_word_previous(state); | |
13319 state->select_end = state->cursor; | |
13320 nk_textedit_clamp(state ); | |
13321 } else { | |
13322 if (NK_TEXT_HAS_SELECTION(state)) | |
13323 nk_textedit_move_to_first(state); | |
13324 else { | |
13325 state->cursor = nk_textedit_move_to_word_previous(state); | |
13326 nk_textedit_clamp(state ); | |
13327 } | |
13328 } break; | |
13329 | |
13330 case NK_KEY_TEXT_WORD_RIGHT: | |
13331 if (shift_mod) { | |
13332 if( !NK_TEXT_HAS_SELECTION( state ) ) | |
13333 nk_textedit_prep_selection_at_cursor(state); | |
13334 state->cursor = nk_textedit_move_to_word_next(state); | |
13335 state->select_end = state->cursor; | |
13336 nk_textedit_clamp(state); | |
13337 } else { | |
13338 if (NK_TEXT_HAS_SELECTION(state)) | |
13339 nk_textedit_move_to_last(state); | |
13340 else { | |
13341 state->cursor = nk_textedit_move_to_word_next(state); | |
13342 nk_textedit_clamp(state ); | |
13343 } | |
13344 } break; | |
13345 | |
13346 case NK_KEY_DOWN: { | |
13347 struct nk_text_find find; | |
13348 struct nk_text_edit_row row; | |
13349 int i, sel = shift_mod; | |
13350 | |
13351 if (state->single_line) { | |
13352 /* on windows, up&down in single-line behave like left&right */ | |
13353 key = NK_KEY_RIGHT; | |
13354 goto retry; | |
13355 } | |
13356 | |
13357 if (sel) | |
13358 nk_textedit_prep_selection_at_cursor(state); | |
13359 else if (NK_TEXT_HAS_SELECTION(state)) | |
13360 nk_textedit_move_to_last(state); | |
13361 | |
13362 /* compute current position of cursor point */ | |
13363 nk_textedit_clamp(state); | |
13364 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, | |
13365 font, row_height); | |
13366 | |
13367 /* now find character position down a row */ | |
13368 if (find.length) | |
13369 { | |
13370 float x; | |
13371 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; | |
13372 int start = find.first_char + find.length; | |
13373 | |
13374 state->cursor = start; | |
13375 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); | |
13376 x = row.x0; | |
13377 | |
13378 for (i=0; i < row.num_chars && x < row.x1; ++i) { | |
13379 float dx = nk_textedit_get_width(state, start, i, font); | |
13380 x += dx; | |
13381 if (x > goal_x) | |
13382 break; | |
13383 ++state->cursor; | |
13384 } | |
13385 nk_textedit_clamp(state); | |
13386 | |
13387 state->has_preferred_x = 1; | |
13388 state->preferred_x = goal_x; | |
13389 if (sel) | |
13390 state->select_end = state->cursor; | |
13391 } | |
13392 } break; | |
13393 | |
13394 case NK_KEY_UP: { | |
13395 struct nk_text_find find; | |
13396 struct nk_text_edit_row row; | |
13397 int i, sel = shift_mod; | |
13398 | |
13399 if (state->single_line) { | |
13400 /* on windows, up&down become left&right */ | |
13401 key = NK_KEY_LEFT; | |
13402 goto retry; | |
13403 } | |
13404 | |
13405 if (sel) | |
13406 nk_textedit_prep_selection_at_cursor(state); | |
13407 else if (NK_TEXT_HAS_SELECTION(state)) | |
13408 nk_textedit_move_to_first(state); | |
13409 | |
13410 /* compute current position of cursor point */ | |
13411 nk_textedit_clamp(state); | |
13412 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, | |
13413 font, row_height); | |
13414 | |
13415 /* can only go up if there's a previous row */ | |
13416 if (find.prev_first != find.first_char) { | |
13417 /* now find character position up a row */ | |
13418 float x; | |
13419 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; | |
13420 | |
13421 state->cursor = find.prev_first; | |
13422 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); | |
13423 x = row.x0; | |
13424 | |
13425 for (i=0; i < row.num_chars && x < row.x1; ++i) { | |
13426 float dx = nk_textedit_get_width(state, find.prev_first, i, font); | |
13427 x += dx; | |
13428 if (x > goal_x) | |
13429 break; | |
13430 ++state->cursor; | |
13431 } | |
13432 nk_textedit_clamp(state); | |
13433 | |
13434 state->has_preferred_x = 1; | |
13435 state->preferred_x = goal_x; | |
13436 if (sel) state->select_end = state->cursor; | |
13437 } | |
13438 } break; | |
13439 | |
13440 case NK_KEY_DEL: | |
13441 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) | |
13442 break; | |
13443 if (NK_TEXT_HAS_SELECTION(state)) | |
13444 nk_textedit_delete_selection(state); | |
13445 else { | |
13446 int n = state->string.len; | |
13447 if (state->cursor < n) | |
13448 nk_textedit_delete(state, state->cursor, 1); | |
13449 } | |
13450 state->has_preferred_x = 0; | |
13451 break; | |
13452 | |
13453 case NK_KEY_BACKSPACE: | |
13454 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) | |
13455 break; | |
13456 if (NK_TEXT_HAS_SELECTION(state)) | |
13457 nk_textedit_delete_selection(state); | |
13458 else { | |
13459 nk_textedit_clamp(state); | |
13460 if (state->cursor > 0) { | |
13461 nk_textedit_delete(state, state->cursor-1, 1); | |
13462 --state->cursor; | |
13463 } | |
13464 } | |
13465 state->has_preferred_x = 0; | |
13466 break; | |
13467 | |
13468 case NK_KEY_TEXT_START: | |
13469 if (shift_mod) { | |
13470 nk_textedit_prep_selection_at_cursor(state); | |
13471 state->cursor = state->select_end = 0; | |
13472 state->has_preferred_x = 0; | |
13473 } else { | |
13474 state->cursor = state->select_start = state->select_end = 0; | |
13475 state->has_preferred_x = 0; | |
13476 } | |
13477 break; | |
13478 | |
13479 case NK_KEY_TEXT_END: | |
13480 if (shift_mod) { | |
13481 nk_textedit_prep_selection_at_cursor(state); | |
13482 state->cursor = state->select_end = state->string.len; | |
13483 state->has_preferred_x = 0; | |
13484 } else { | |
13485 state->cursor = state->string.len; | |
13486 state->select_start = state->select_end = 0; | |
13487 state->has_preferred_x = 0; | |
13488 } | |
13489 break; | |
13490 | |
13491 case NK_KEY_TEXT_LINE_START: { | |
13492 if (shift_mod) { | |
13493 struct nk_text_find find; | |
13494 nk_textedit_clamp(state); | |
13495 nk_textedit_prep_selection_at_cursor(state); | |
13496 if (state->string.len && state->cursor == state->string.len) | |
13497 --state->cursor; | |
13498 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, | |
13499 font, row_height); | |
13500 state->cursor = state->select_end = find.first_char; | |
13501 state->has_preferred_x = 0; | |
13502 } else { | |
13503 struct nk_text_find find; | |
13504 if (state->string.len && state->cursor == state->string.len) | |
13505 --state->cursor; | |
13506 nk_textedit_clamp(state); | |
13507 nk_textedit_move_to_first(state); | |
13508 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, | |
13509 font, row_height); | |
13510 state->cursor = find.first_char; | |
13511 state->has_preferred_x = 0; | |
13512 } | |
13513 } break; | |
13514 | |
13515 case NK_KEY_TEXT_LINE_END: { | |
13516 if (shift_mod) { | |
13517 struct nk_text_find find; | |
13518 nk_textedit_clamp(state); | |
13519 nk_textedit_prep_selection_at_cursor(state); | |
13520 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, | |
13521 font, row_height); | |
13522 state->has_preferred_x = 0; | |
13523 state->cursor = find.first_char + find.length; | |
13524 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') | |
13525 --state->cursor; | |
13526 state->select_end = state->cursor; | |
13527 } else { | |
13528 struct nk_text_find find; | |
13529 nk_textedit_clamp(state); | |
13530 nk_textedit_move_to_first(state); | |
13531 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, | |
13532 font, row_height); | |
13533 | |
13534 state->has_preferred_x = 0; | |
13535 state->cursor = find.first_char + find.length; | |
13536 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') | |
13537 --state->cursor; | |
13538 }} break; | |
13539 } | |
13540 } | |
13541 | |
13542 NK_INTERN void | |
13543 nk_textedit_flush_redo(struct nk_text_undo_state *state) | |
13544 { | |
13545 state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; | |
13546 state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; | |
13547 } | |
13548 | |
13549 NK_INTERN void | |
13550 nk_textedit_discard_undo(struct nk_text_undo_state *state) | |
13551 { | |
13552 /* discard the oldest entry in the undo list */ | |
13553 if (state->undo_point > 0) { | |
13554 /* if the 0th undo state has characters, clean those up */ | |
13555 if (state->undo_rec[0].char_storage >= 0) { | |
13556 int n = state->undo_rec[0].insert_length, i; | |
13557 /* delete n characters from all other records */ | |
13558 state->undo_char_point = (short)(state->undo_char_point - n); | |
13559 NK_MEMCPY(state->undo_char, state->undo_char + n, | |
13560 (nk_size)state->undo_char_point*sizeof(nk_rune)); | |
13561 for (i=0; i < state->undo_point; ++i) { | |
13562 if (state->undo_rec[i].char_storage >= 0) | |
13563 state->undo_rec[i].char_storage = (short) | |
13564 (state->undo_rec[i].char_storage - n); | |
13565 } | |
13566 } | |
13567 --state->undo_point; | |
13568 NK_MEMCPY(state->undo_rec, state->undo_rec+1, | |
13569 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); | |
13570 } | |
13571 } | |
13572 | |
13573 NK_INTERN void | |
13574 nk_textedit_discard_redo(struct nk_text_undo_state *state) | |
13575 { | |
13576 /* discard the oldest entry in the redo list--it's bad if this | |
13577 ever happens, but because undo & redo have to store the actual | |
13578 characters in different cases, the redo character buffer can | |
13579 fill up even though the undo buffer didn't */ | |
13580 nk_size num; | |
13581 int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; | |
13582 if (state->redo_point <= k) { | |
13583 /* if the k'th undo state has characters, clean those up */ | |
13584 if (state->undo_rec[k].char_storage >= 0) { | |
13585 int n = state->undo_rec[k].insert_length, i; | |
13586 /* delete n characters from all other records */ | |
13587 state->redo_char_point = (short)(state->redo_char_point + n); | |
13588 num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); | |
13589 NK_MEMCPY(state->undo_char + state->redo_char_point, | |
13590 state->undo_char + state->redo_char_point-n, num * sizeof(char)); | |
13591 for (i = state->redo_point; i < k; ++i) { | |
13592 if (state->undo_rec[i].char_storage >= 0) { | |
13593 state->undo_rec[i].char_storage = (short) | |
13594 (state->undo_rec[i].char_storage + n); | |
13595 } | |
13596 } | |
13597 } | |
13598 ++state->redo_point; | |
13599 num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); | |
13600 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, | |
13601 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); | |
13602 } | |
13603 } | |
13604 | |
13605 NK_INTERN struct nk_text_undo_record* | |
13606 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) | |
13607 { | |
13608 /* any time we create a new undo record, we discard redo*/ | |
13609 nk_textedit_flush_redo(state); | |
13610 | |
13611 /* if we have no free records, we have to make room, | |
13612 * by sliding the existing records down */ | |
13613 if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) | |
13614 nk_textedit_discard_undo(state); | |
13615 | |
13616 /* if the characters to store won't possibly fit in the buffer, | |
13617 * we can't undo */ | |
13618 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { | |
13619 state->undo_point = 0; | |
13620 state->undo_char_point = 0; | |
13621 return 0; | |
13622 } | |
13623 | |
13624 /* if we don't have enough free characters in the buffer, | |
13625 * we have to make room */ | |
13626 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) | |
13627 nk_textedit_discard_undo(state); | |
13628 return &state->undo_rec[state->undo_point++]; | |
13629 } | |
13630 | |
13631 NK_INTERN nk_rune* | |
13632 nk_textedit_createundo(struct nk_text_undo_state *state, int pos, | |
13633 int insert_len, int delete_len) | |
13634 { | |
13635 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); | |
13636 if (r == 0) | |
13637 return 0; | |
13638 | |
13639 r->where = pos; | |
13640 r->insert_length = (short) insert_len; | |
13641 r->delete_length = (short) delete_len; | |
13642 | |
13643 if (insert_len == 0) { | |
13644 r->char_storage = -1; | |
13645 return 0; | |
13646 } else { | |
13647 r->char_storage = state->undo_char_point; | |
13648 state->undo_char_point = (short)(state->undo_char_point + insert_len); | |
13649 return &state->undo_char[r->char_storage]; | |
13650 } | |
13651 } | |
13652 | |
13653 NK_API void | |
13654 nk_textedit_undo(struct nk_text_edit *state) | |
13655 { | |
13656 struct nk_text_undo_state *s = &state->undo; | |
13657 struct nk_text_undo_record u, *r; | |
13658 if (s->undo_point == 0) | |
13659 return; | |
13660 | |
13661 /* we need to do two things: apply the undo record, and create a redo record */ | |
13662 u = s->undo_rec[s->undo_point-1]; | |
13663 r = &s->undo_rec[s->redo_point-1]; | |
13664 r->char_storage = -1; | |
13665 | |
13666 r->insert_length = u.delete_length; | |
13667 r->delete_length = u.insert_length; | |
13668 r->where = u.where; | |
13669 | |
13670 if (u.delete_length) | |
13671 { | |
13672 /* if the undo record says to delete characters, then the redo record will | |
13673 need to re-insert the characters that get deleted, so we need to store | |
13674 them. | |
13675 there are three cases: | |
13676 - there's enough room to store the characters | |
13677 - characters stored for *redoing* don't leave room for redo | |
13678 - characters stored for *undoing* don't leave room for redo | |
13679 if the last is true, we have to bail */ | |
13680 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { | |
13681 /* the undo records take up too much character space; there's no space | |
13682 * to store the redo characters */ | |
13683 r->insert_length = 0; | |
13684 } else { | |
13685 int i; | |
13686 /* there's definitely room to store the characters eventually */ | |
13687 while (s->undo_char_point + u.delete_length > s->redo_char_point) { | |
13688 /* there's currently not enough room, so discard a redo record */ | |
13689 nk_textedit_discard_redo(s); | |
13690 /* should never happen: */ | |
13691 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) | |
13692 return; | |
13693 } | |
13694 | |
13695 r = &s->undo_rec[s->redo_point-1]; | |
13696 r->char_storage = (short)(s->redo_char_point - u.delete_length); | |
13697 s->redo_char_point = (short)(s->redo_char_point - u.delete_length); | |
13698 | |
13699 /* now save the characters */ | |
13700 for (i=0; i < u.delete_length; ++i) | |
13701 s->undo_char[r->char_storage + i] = | |
13702 nk_str_rune_at(&state->string, u.where + i); | |
13703 } | |
13704 /* now we can carry out the deletion */ | |
13705 nk_str_delete_runes(&state->string, u.where, u.delete_length); | |
13706 } | |
13707 | |
13708 /* check type of recorded action: */ | |
13709 if (u.insert_length) { | |
13710 /* easy case: was a deletion, so we need to insert n characters */ | |
13711 nk_str_insert_text_runes(&state->string, u.where, | |
13712 &s->undo_char[u.char_storage], u.insert_length); | |
13713 s->undo_char_point = (short)(s->undo_char_point - u.insert_length); | |
13714 } | |
13715 state->cursor = (short)(u.where + u.insert_length); | |
13716 | |
13717 s->undo_point--; | |
13718 s->redo_point--; | |
13719 } | |
13720 | |
13721 NK_API void | |
13722 nk_textedit_redo(struct nk_text_edit *state) | |
13723 { | |
13724 struct nk_text_undo_state *s = &state->undo; | |
13725 struct nk_text_undo_record *u, r; | |
13726 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) | |
13727 return; | |
13728 | |
13729 /* we need to do two things: apply the redo record, and create an undo record */ | |
13730 u = &s->undo_rec[s->undo_point]; | |
13731 r = s->undo_rec[s->redo_point]; | |
13732 | |
13733 /* we KNOW there must be room for the undo record, because the redo record | |
13734 was derived from an undo record */ | |
13735 u->delete_length = r.insert_length; | |
13736 u->insert_length = r.delete_length; | |
13737 u->where = r.where; | |
13738 u->char_storage = -1; | |
13739 | |
13740 if (r.delete_length) { | |
13741 /* the redo record requires us to delete characters, so the undo record | |
13742 needs to store the characters */ | |
13743 if (s->undo_char_point + u->insert_length > s->redo_char_point) { | |
13744 u->insert_length = 0; | |
13745 u->delete_length = 0; | |
13746 } else { | |
13747 int i; | |
13748 u->char_storage = s->undo_char_point; | |
13749 s->undo_char_point = (short)(s->undo_char_point + u->insert_length); | |
13750 | |
13751 /* now save the characters */ | |
13752 for (i=0; i < u->insert_length; ++i) { | |
13753 s->undo_char[u->char_storage + i] = | |
13754 nk_str_rune_at(&state->string, u->where + i); | |
13755 } | |
13756 } | |
13757 nk_str_delete_runes(&state->string, r.where, r.delete_length); | |
13758 } | |
13759 | |
13760 if (r.insert_length) { | |
13761 /* easy case: need to insert n characters */ | |
13762 nk_str_insert_text_runes(&state->string, r.where, | |
13763 &s->undo_char[r.char_storage], r.insert_length); | |
13764 } | |
13765 state->cursor = r.where + r.insert_length; | |
13766 | |
13767 s->undo_point++; | |
13768 s->redo_point++; | |
13769 } | |
13770 | |
13771 NK_INTERN void | |
13772 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) | |
13773 { | |
13774 nk_textedit_createundo(&state->undo, where, 0, length); | |
13775 } | |
13776 | |
13777 NK_INTERN void | |
13778 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) | |
13779 { | |
13780 int i; | |
13781 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); | |
13782 if (p) { | |
13783 for (i=0; i < length; ++i) | |
13784 p[i] = nk_str_rune_at(&state->string, where+i); | |
13785 } | |
13786 } | |
13787 | |
13788 NK_INTERN void | |
13789 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, | |
13790 int old_length, int new_length) | |
13791 { | |
13792 int i; | |
13793 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); | |
13794 if (p) { | |
13795 for (i=0; i < old_length; ++i) | |
13796 p[i] = nk_str_rune_at(&state->string, where+i); | |
13797 } | |
13798 } | |
13799 | |
13800 NK_INTERN void | |
13801 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, | |
13802 nk_plugin_filter filter) | |
13803 { | |
13804 /* reset the state to default */ | |
13805 state->undo.undo_point = 0; | |
13806 state->undo.undo_char_point = 0; | |
13807 state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; | |
13808 state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; | |
13809 state->select_end = state->select_start = 0; | |
13810 state->cursor = 0; | |
13811 state->has_preferred_x = 0; | |
13812 state->preferred_x = 0; | |
13813 state->cursor_at_end_of_line = 0; | |
13814 state->initialized = 1; | |
13815 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); | |
13816 state->mode = NK_TEXT_EDIT_MODE_VIEW; | |
13817 state->filter = filter; | |
13818 state->scrollbar = nk_vec2(0,0); | |
13819 } | |
13820 | |
13821 NK_API void | |
13822 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) | |
13823 { | |
13824 NK_ASSERT(state); | |
13825 NK_ASSERT(memory); | |
13826 if (!state || !memory || !size) return; | |
13827 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); | |
13828 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); | |
13829 nk_str_init_fixed(&state->string, memory, size); | |
13830 } | |
13831 | |
13832 NK_API void | |
13833 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) | |
13834 { | |
13835 NK_ASSERT(state); | |
13836 NK_ASSERT(alloc); | |
13837 if (!state || !alloc) return; | |
13838 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); | |
13839 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); | |
13840 nk_str_init(&state->string, alloc, size); | |
13841 } | |
13842 | |
13843 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
13844 NK_API void | |
13845 nk_textedit_init_default(struct nk_text_edit *state) | |
13846 { | |
13847 NK_ASSERT(state); | |
13848 if (!state) return; | |
13849 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); | |
13850 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); | |
13851 nk_str_init_default(&state->string); | |
13852 } | |
13853 #endif | |
13854 | |
13855 NK_API void | |
13856 nk_textedit_select_all(struct nk_text_edit *state) | |
13857 { | |
13858 NK_ASSERT(state); | |
13859 state->select_start = 0; | |
13860 state->select_end = state->string.len; | |
13861 } | |
13862 | |
13863 NK_API void | |
13864 nk_textedit_free(struct nk_text_edit *state) | |
13865 { | |
13866 NK_ASSERT(state); | |
13867 if (!state) return; | |
13868 nk_str_free(&state->string); | |
13869 } | |
13870 | |
13871 /* =============================================================== | |
13872 * | |
13873 * TEXT WIDGET | |
13874 * | |
13875 * ===============================================================*/ | |
13876 #define nk_widget_state_reset(s)\ | |
13877 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ | |
13878 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ | |
13879 else (*(s)) = NK_WIDGET_STATE_INACTIVE; | |
13880 | |
13881 struct nk_text { | |
13882 struct nk_vec2 padding; | |
13883 struct nk_color background; | |
13884 struct nk_color text; | |
13885 }; | |
13886 | |
13887 NK_INTERN void | |
13888 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, | |
13889 const char *string, int len, const struct nk_text *t, | |
13890 nk_flags a, const struct nk_user_font *f) | |
13891 { | |
13892 struct nk_rect label; | |
13893 float text_width; | |
13894 | |
13895 NK_ASSERT(o); | |
13896 NK_ASSERT(t); | |
13897 if (!o || !t) return; | |
13898 | |
13899 b.h = NK_MAX(b.h, 2 * t->padding.y); | |
13900 label.x = 0; label.w = 0; | |
13901 label.y = b.y + t->padding.y; | |
13902 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); | |
13903 | |
13904 text_width = f->width(f->userdata, f->height, (const char*)string, len); | |
13905 text_width += (2.0f * t->padding.x); | |
13906 | |
13907 /* align in x-axis */ | |
13908 if (a & NK_TEXT_ALIGN_LEFT) { | |
13909 label.x = b.x + t->padding.x; | |
13910 label.w = NK_MAX(0, b.w - 2 * t->padding.x); | |
13911 } else if (a & NK_TEXT_ALIGN_CENTERED) { | |
13912 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); | |
13913 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); | |
13914 label.x = NK_MAX(b.x + t->padding.x, label.x); | |
13915 label.w = NK_MIN(b.x + b.w, label.x + label.w); | |
13916 if (label.w >= label.x) label.w -= label.x; | |
13917 } else if (a & NK_TEXT_ALIGN_RIGHT) { | |
13918 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); | |
13919 label.w = (float)text_width + 2 * t->padding.x; | |
13920 } else return; | |
13921 | |
13922 /* align in y-axis */ | |
13923 if (a & NK_TEXT_ALIGN_MIDDLE) { | |
13924 label.y = b.y + b.h/2.0f - (float)f->height/2.0f; | |
13925 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); | |
13926 } else if (a & NK_TEXT_ALIGN_BOTTOM) { | |
13927 label.y = b.y + b.h - f->height; | |
13928 label.h = f->height; | |
13929 } | |
13930 nk_draw_text(o, label, (const char*)string, | |
13931 len, f, t->background, t->text); | |
13932 } | |
13933 | |
13934 NK_INTERN void | |
13935 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, | |
13936 const char *string, int len, const struct nk_text *t, | |
13937 const struct nk_user_font *f) | |
13938 { | |
13939 float width; | |
13940 int glyphs = 0; | |
13941 int fitting = 0; | |
13942 int done = 0; | |
13943 struct nk_rect line; | |
13944 struct nk_text text; | |
13945 NK_INTERN nk_rune seperator[] = {' '}; | |
13946 | |
13947 NK_ASSERT(o); | |
13948 NK_ASSERT(t); | |
13949 if (!o || !t) return; | |
13950 | |
13951 text.padding = nk_vec2(0,0); | |
13952 text.background = t->background; | |
13953 text.text = t->text; | |
13954 | |
13955 b.w = NK_MAX(b.w, 2 * t->padding.x); | |
13956 b.h = NK_MAX(b.h, 2 * t->padding.y); | |
13957 b.h = b.h - 2 * t->padding.y; | |
13958 | |
13959 line.x = b.x + t->padding.x; | |
13960 line.y = b.y + t->padding.y; | |
13961 line.w = b.w - 2 * t->padding.x; | |
13962 line.h = 2 * t->padding.y + f->height; | |
13963 | |
13964 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); | |
13965 while (done < len) { | |
13966 if (!fitting || line.y + line.h >= (b.y + b.h)) break; | |
13967 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); | |
13968 done += fitting; | |
13969 line.y += f->height + 2 * t->padding.y; | |
13970 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); | |
13971 } | |
13972 } | |
13973 | |
13974 /* =============================================================== | |
13975 * | |
13976 * BUTTON | |
13977 * | |
13978 * ===============================================================*/ | |
13979 NK_INTERN void | |
13980 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, | |
13981 struct nk_rect content, struct nk_color background, struct nk_color foreground, | |
13982 float border_width, const struct nk_user_font *font) | |
13983 { | |
13984 switch (type) { | |
13985 case NK_SYMBOL_X: | |
13986 case NK_SYMBOL_UNDERSCORE: | |
13987 case NK_SYMBOL_PLUS: | |
13988 case NK_SYMBOL_MINUS: { | |
13989 /* single character text symbol */ | |
13990 const char *X = (type == NK_SYMBOL_X) ? "x": | |
13991 (type == NK_SYMBOL_UNDERSCORE) ? "_": | |
13992 (type == NK_SYMBOL_PLUS) ? "+": "-"; | |
13993 struct nk_text text; | |
13994 text.padding = nk_vec2(0,0); | |
13995 text.background = background; | |
13996 text.text = foreground; | |
13997 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); | |
13998 } break; | |
13999 case NK_SYMBOL_CIRCLE_SOLID: | |
14000 case NK_SYMBOL_CIRCLE_OUTLINE: | |
14001 case NK_SYMBOL_RECT_SOLID: | |
14002 case NK_SYMBOL_RECT_OUTLINE: { | |
14003 /* simple empty/filled shapes */ | |
14004 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { | |
14005 nk_fill_rect(out, content, 0, foreground); | |
14006 if (type == NK_SYMBOL_RECT_OUTLINE) | |
14007 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); | |
14008 } else { | |
14009 nk_fill_circle(out, content, foreground); | |
14010 if (type == NK_SYMBOL_CIRCLE_OUTLINE) | |
14011 nk_fill_circle(out, nk_shrink_rect(content, 1), background); | |
14012 } | |
14013 } break; | |
14014 case NK_SYMBOL_TRIANGLE_UP: | |
14015 case NK_SYMBOL_TRIANGLE_DOWN: | |
14016 case NK_SYMBOL_TRIANGLE_LEFT: | |
14017 case NK_SYMBOL_TRIANGLE_RIGHT: { | |
14018 enum nk_heading heading; | |
14019 struct nk_vec2 points[3]; | |
14020 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : | |
14021 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: | |
14022 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; | |
14023 nk_triangle_from_direction(points, content, 0, 0, heading); | |
14024 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, | |
14025 points[2].x, points[2].y, foreground); | |
14026 } break; | |
14027 default: | |
14028 case NK_SYMBOL_NONE: | |
14029 case NK_SYMBOL_MAX: break; | |
14030 } | |
14031 } | |
14032 | |
14033 NK_INTERN int | |
14034 nk_button_behavior(nk_flags *state, struct nk_rect r, | |
14035 const struct nk_input *i, enum nk_button_behavior behavior) | |
14036 { | |
14037 int ret = 0; | |
14038 nk_widget_state_reset(state); | |
14039 if (!i) return 0; | |
14040 if (nk_input_is_mouse_hovering_rect(i, r)) { | |
14041 *state = NK_WIDGET_STATE_HOVERED; | |
14042 if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) | |
14043 *state = NK_WIDGET_STATE_ACTIVE; | |
14044 if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) { | |
14045 ret = (behavior != NK_BUTTON_DEFAULT) ? | |
14046 nk_input_is_mouse_down(i, NK_BUTTON_LEFT): | |
14047 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE | |
14048 nk_input_is_mouse_released(i, NK_BUTTON_LEFT); | |
14049 #else | |
14050 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); | |
14051 #endif | |
14052 } | |
14053 } | |
14054 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) | |
14055 *state |= NK_WIDGET_STATE_ENTERED; | |
14056 else if (nk_input_is_mouse_prev_hovering_rect(i, r)) | |
14057 *state |= NK_WIDGET_STATE_LEFT; | |
14058 return ret; | |
14059 } | |
14060 | |
14061 NK_INTERN const struct nk_style_item* | |
14062 nk_draw_button(struct nk_command_buffer *out, | |
14063 const struct nk_rect *bounds, nk_flags state, | |
14064 const struct nk_style_button *style) | |
14065 { | |
14066 const struct nk_style_item *background; | |
14067 if (state & NK_WIDGET_STATE_HOVER) | |
14068 background = &style->hover; | |
14069 else if (state & NK_WIDGET_STATE_ACTIVED) | |
14070 background = &style->active; | |
14071 else background = &style->normal; | |
14072 | |
14073 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
14074 nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
14075 } else { | |
14076 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
14077 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); | |
14078 } | |
14079 return background; | |
14080 } | |
14081 | |
14082 NK_INTERN int | |
14083 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, | |
14084 const struct nk_style_button *style, const struct nk_input *in, | |
14085 enum nk_button_behavior behavior, struct nk_rect *content) | |
14086 { | |
14087 struct nk_rect bounds; | |
14088 NK_ASSERT(style); | |
14089 NK_ASSERT(state); | |
14090 NK_ASSERT(out); | |
14091 if (!out || !style) | |
14092 return nk_false; | |
14093 | |
14094 /* calculate button content space */ | |
14095 content->x = r.x + style->padding.x + style->border + style->rounding; | |
14096 content->y = r.y + style->padding.y + style->border + style->rounding; | |
14097 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); | |
14098 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); | |
14099 | |
14100 /* execute button behavior */ | |
14101 bounds.x = r.x - style->touch_padding.x; | |
14102 bounds.y = r.y - style->touch_padding.y; | |
14103 bounds.w = r.w + 2 * style->touch_padding.x; | |
14104 bounds.h = r.h + 2 * style->touch_padding.y; | |
14105 return nk_button_behavior(state, bounds, in, behavior); | |
14106 } | |
14107 | |
14108 NK_INTERN void | |
14109 nk_draw_button_text(struct nk_command_buffer *out, | |
14110 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, | |
14111 const struct nk_style_button *style, const char *txt, int len, | |
14112 nk_flags text_alignment, const struct nk_user_font *font) | |
14113 { | |
14114 struct nk_text text; | |
14115 const struct nk_style_item *background; | |
14116 background = nk_draw_button(out, bounds, state, style); | |
14117 | |
14118 /* select correct colors/images */ | |
14119 if (background->type == NK_STYLE_ITEM_COLOR) | |
14120 text.background = background->data.color; | |
14121 else text.background = style->text_background; | |
14122 if (state & NK_WIDGET_STATE_HOVER) | |
14123 text.text = style->text_hover; | |
14124 else if (state & NK_WIDGET_STATE_ACTIVED) | |
14125 text.text = style->text_active; | |
14126 else text.text = style->text_normal; | |
14127 | |
14128 text.padding = nk_vec2(0,0); | |
14129 nk_widget_text(out, *content, txt, len, &text, text_alignment, font); | |
14130 } | |
14131 | |
14132 NK_INTERN int | |
14133 nk_do_button_text(nk_flags *state, | |
14134 struct nk_command_buffer *out, struct nk_rect bounds, | |
14135 const char *string, int len, nk_flags align, enum nk_button_behavior behavior, | |
14136 const struct nk_style_button *style, const struct nk_input *in, | |
14137 const struct nk_user_font *font) | |
14138 { | |
14139 struct nk_rect content; | |
14140 int ret = nk_false; | |
14141 | |
14142 NK_ASSERT(state); | |
14143 NK_ASSERT(style); | |
14144 NK_ASSERT(out); | |
14145 NK_ASSERT(string); | |
14146 NK_ASSERT(font); | |
14147 if (!out || !style || !font || !string) | |
14148 return nk_false; | |
14149 | |
14150 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); | |
14151 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14152 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); | |
14153 if (style->draw_end) style->draw_end(out, style->userdata); | |
14154 return ret; | |
14155 } | |
14156 | |
14157 NK_INTERN void | |
14158 nk_draw_button_symbol(struct nk_command_buffer *out, | |
14159 const struct nk_rect *bounds, const struct nk_rect *content, | |
14160 nk_flags state, const struct nk_style_button *style, | |
14161 enum nk_symbol_type type, const struct nk_user_font *font) | |
14162 { | |
14163 struct nk_color sym, bg; | |
14164 const struct nk_style_item *background; | |
14165 | |
14166 /* select correct colors/images */ | |
14167 background = nk_draw_button(out, bounds, state, style); | |
14168 if (background->type == NK_STYLE_ITEM_COLOR) | |
14169 bg = background->data.color; | |
14170 else bg = style->text_background; | |
14171 | |
14172 if (state & NK_WIDGET_STATE_HOVER) | |
14173 sym = style->text_hover; | |
14174 else if (state & NK_WIDGET_STATE_ACTIVED) | |
14175 sym = style->text_active; | |
14176 else sym = style->text_normal; | |
14177 nk_draw_symbol(out, type, *content, bg, sym, 1, font); | |
14178 } | |
14179 | |
14180 NK_INTERN int | |
14181 nk_do_button_symbol(nk_flags *state, | |
14182 struct nk_command_buffer *out, struct nk_rect bounds, | |
14183 enum nk_symbol_type symbol, enum nk_button_behavior behavior, | |
14184 const struct nk_style_button *style, const struct nk_input *in, | |
14185 const struct nk_user_font *font) | |
14186 { | |
14187 int ret; | |
14188 struct nk_rect content; | |
14189 | |
14190 NK_ASSERT(state); | |
14191 NK_ASSERT(style); | |
14192 NK_ASSERT(font); | |
14193 NK_ASSERT(out); | |
14194 if (!out || !style || !font || !state) | |
14195 return nk_false; | |
14196 | |
14197 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); | |
14198 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14199 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); | |
14200 if (style->draw_end) style->draw_end(out, style->userdata); | |
14201 return ret; | |
14202 } | |
14203 | |
14204 NK_INTERN void | |
14205 nk_draw_button_image(struct nk_command_buffer *out, | |
14206 const struct nk_rect *bounds, const struct nk_rect *content, | |
14207 nk_flags state, const struct nk_style_button *style, const struct nk_image *img) | |
14208 { | |
14209 nk_draw_button(out, bounds, state, style); | |
14210 nk_draw_image(out, *content, img, nk_white); | |
14211 } | |
14212 | |
14213 NK_INTERN int | |
14214 nk_do_button_image(nk_flags *state, | |
14215 struct nk_command_buffer *out, struct nk_rect bounds, | |
14216 struct nk_image img, enum nk_button_behavior b, | |
14217 const struct nk_style_button *style, const struct nk_input *in) | |
14218 { | |
14219 int ret; | |
14220 struct nk_rect content; | |
14221 | |
14222 NK_ASSERT(state); | |
14223 NK_ASSERT(style); | |
14224 NK_ASSERT(out); | |
14225 if (!out || !style || !state) | |
14226 return nk_false; | |
14227 | |
14228 ret = nk_do_button(state, out, bounds, style, in, b, &content); | |
14229 content.x += style->image_padding.x; | |
14230 content.y += style->image_padding.y; | |
14231 content.w -= 2 * style->image_padding.x; | |
14232 content.h -= 2 * style->image_padding.y; | |
14233 | |
14234 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14235 nk_draw_button_image(out, &bounds, &content, *state, style, &img); | |
14236 if (style->draw_end) style->draw_end(out, style->userdata); | |
14237 return ret; | |
14238 } | |
14239 | |
14240 NK_INTERN void | |
14241 nk_draw_button_text_symbol(struct nk_command_buffer *out, | |
14242 const struct nk_rect *bounds, const struct nk_rect *label, | |
14243 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, | |
14244 const char *str, int len, enum nk_symbol_type type, | |
14245 const struct nk_user_font *font) | |
14246 { | |
14247 struct nk_color sym; | |
14248 struct nk_text text; | |
14249 const struct nk_style_item *background; | |
14250 | |
14251 /* select correct background colors/images */ | |
14252 background = nk_draw_button(out, bounds, state, style); | |
14253 if (background->type == NK_STYLE_ITEM_COLOR) | |
14254 text.background = background->data.color; | |
14255 else text.background = style->text_background; | |
14256 | |
14257 /* select correct text colors */ | |
14258 if (state & NK_WIDGET_STATE_HOVER) { | |
14259 sym = style->text_hover; | |
14260 text.text = style->text_hover; | |
14261 } else if (state & NK_WIDGET_STATE_ACTIVED) { | |
14262 sym = style->text_active; | |
14263 text.text = style->text_active; | |
14264 } else { | |
14265 sym = style->text_normal; | |
14266 text.text = style->text_normal; | |
14267 } | |
14268 | |
14269 text.padding = nk_vec2(0,0); | |
14270 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); | |
14271 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); | |
14272 } | |
14273 | |
14274 NK_INTERN int | |
14275 nk_do_button_text_symbol(nk_flags *state, | |
14276 struct nk_command_buffer *out, struct nk_rect bounds, | |
14277 enum nk_symbol_type symbol, const char *str, int len, nk_flags align, | |
14278 enum nk_button_behavior behavior, const struct nk_style_button *style, | |
14279 const struct nk_user_font *font, const struct nk_input *in) | |
14280 { | |
14281 int ret; | |
14282 struct nk_rect tri = {0,0,0,0}; | |
14283 struct nk_rect content; | |
14284 | |
14285 NK_ASSERT(style); | |
14286 NK_ASSERT(out); | |
14287 NK_ASSERT(font); | |
14288 if (!out || !style || !font) | |
14289 return nk_false; | |
14290 | |
14291 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); | |
14292 tri.y = content.y + (content.h/2) - font->height/2; | |
14293 tri.w = font->height; tri.h = font->height; | |
14294 if (align & NK_TEXT_ALIGN_LEFT) { | |
14295 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); | |
14296 tri.x = NK_MAX(tri.x, 0); | |
14297 } else tri.x = content.x + 2 * style->padding.x; | |
14298 | |
14299 /* draw button */ | |
14300 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14301 nk_draw_button_text_symbol(out, &bounds, &content, &tri, | |
14302 *state, style, str, len, symbol, font); | |
14303 if (style->draw_end) style->draw_end(out, style->userdata); | |
14304 return ret; | |
14305 } | |
14306 | |
14307 NK_INTERN void | |
14308 nk_draw_button_text_image(struct nk_command_buffer *out, | |
14309 const struct nk_rect *bounds, const struct nk_rect *label, | |
14310 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, | |
14311 const char *str, int len, const struct nk_user_font *font, | |
14312 const struct nk_image *img) | |
14313 { | |
14314 struct nk_text text; | |
14315 const struct nk_style_item *background; | |
14316 background = nk_draw_button(out, bounds, state, style); | |
14317 | |
14318 /* select correct colors */ | |
14319 if (background->type == NK_STYLE_ITEM_COLOR) | |
14320 text.background = background->data.color; | |
14321 else text.background = style->text_background; | |
14322 if (state & NK_WIDGET_STATE_HOVER) | |
14323 text.text = style->text_hover; | |
14324 else if (state & NK_WIDGET_STATE_ACTIVED) | |
14325 text.text = style->text_active; | |
14326 else text.text = style->text_normal; | |
14327 | |
14328 text.padding = nk_vec2(0,0); | |
14329 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); | |
14330 nk_draw_image(out, *image, img, nk_white); | |
14331 } | |
14332 | |
14333 NK_INTERN int | |
14334 nk_do_button_text_image(nk_flags *state, | |
14335 struct nk_command_buffer *out, struct nk_rect bounds, | |
14336 struct nk_image img, const char* str, int len, nk_flags align, | |
14337 enum nk_button_behavior behavior, const struct nk_style_button *style, | |
14338 const struct nk_user_font *font, const struct nk_input *in) | |
14339 { | |
14340 int ret; | |
14341 struct nk_rect icon; | |
14342 struct nk_rect content; | |
14343 | |
14344 NK_ASSERT(style); | |
14345 NK_ASSERT(state); | |
14346 NK_ASSERT(font); | |
14347 NK_ASSERT(out); | |
14348 if (!out || !font || !style || !str) | |
14349 return nk_false; | |
14350 | |
14351 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); | |
14352 icon.y = bounds.y + style->padding.y; | |
14353 icon.w = icon.h = bounds.h - 2 * style->padding.y; | |
14354 if (align & NK_TEXT_ALIGN_LEFT) { | |
14355 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); | |
14356 icon.x = NK_MAX(icon.x, 0); | |
14357 } else icon.x = bounds.x + 2 * style->padding.x; | |
14358 | |
14359 icon.x += style->image_padding.x; | |
14360 icon.y += style->image_padding.y; | |
14361 icon.w -= 2 * style->image_padding.x; | |
14362 icon.h -= 2 * style->image_padding.y; | |
14363 | |
14364 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14365 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); | |
14366 if (style->draw_end) style->draw_end(out, style->userdata); | |
14367 return ret; | |
14368 } | |
14369 | |
14370 /* =============================================================== | |
14371 * | |
14372 * TOGGLE | |
14373 * | |
14374 * ===============================================================*/ | |
14375 enum nk_toggle_type { | |
14376 NK_TOGGLE_CHECK, | |
14377 NK_TOGGLE_OPTION | |
14378 }; | |
14379 | |
14380 NK_INTERN int | |
14381 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, | |
14382 nk_flags *state, int active) | |
14383 { | |
14384 nk_widget_state_reset(state); | |
14385 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { | |
14386 *state = NK_WIDGET_STATE_ACTIVE; | |
14387 active = !active; | |
14388 } | |
14389 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) | |
14390 *state |= NK_WIDGET_STATE_ENTERED; | |
14391 else if (nk_input_is_mouse_prev_hovering_rect(in, select)) | |
14392 *state |= NK_WIDGET_STATE_LEFT; | |
14393 return active; | |
14394 } | |
14395 | |
14396 NK_INTERN void | |
14397 nk_draw_checkbox(struct nk_command_buffer *out, | |
14398 nk_flags state, const struct nk_style_toggle *style, int active, | |
14399 const struct nk_rect *label, const struct nk_rect *selector, | |
14400 const struct nk_rect *cursors, const char *string, int len, | |
14401 const struct nk_user_font *font) | |
14402 { | |
14403 const struct nk_style_item *background; | |
14404 const struct nk_style_item *cursor; | |
14405 struct nk_text text; | |
14406 | |
14407 /* select correct colors/images */ | |
14408 if (state & NK_WIDGET_STATE_HOVER) { | |
14409 background = &style->hover; | |
14410 cursor = &style->cursor_hover; | |
14411 text.text = style->text_hover; | |
14412 } else if (state & NK_WIDGET_STATE_ACTIVED) { | |
14413 background = &style->hover; | |
14414 cursor = &style->cursor_hover; | |
14415 text.text = style->text_active; | |
14416 } else { | |
14417 background = &style->normal; | |
14418 cursor = &style->cursor_normal; | |
14419 text.text = style->text_normal; | |
14420 } | |
14421 | |
14422 /* draw background and cursor */ | |
14423 if (background->type == NK_STYLE_ITEM_COLOR) { | |
14424 nk_fill_rect(out, *selector, 0, style->border_color); | |
14425 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); | |
14426 } else nk_draw_image(out, *selector, &background->data.image, nk_white); | |
14427 if (active) { | |
14428 if (cursor->type == NK_STYLE_ITEM_IMAGE) | |
14429 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); | |
14430 else nk_fill_rect(out, *cursors, 0, cursor->data.color); | |
14431 } | |
14432 | |
14433 text.padding.x = 0; | |
14434 text.padding.y = 0; | |
14435 text.background = style->text_background; | |
14436 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); | |
14437 } | |
14438 | |
14439 NK_INTERN void | |
14440 nk_draw_option(struct nk_command_buffer *out, | |
14441 nk_flags state, const struct nk_style_toggle *style, int active, | |
14442 const struct nk_rect *label, const struct nk_rect *selector, | |
14443 const struct nk_rect *cursors, const char *string, int len, | |
14444 const struct nk_user_font *font) | |
14445 { | |
14446 const struct nk_style_item *background; | |
14447 const struct nk_style_item *cursor; | |
14448 struct nk_text text; | |
14449 | |
14450 /* select correct colors/images */ | |
14451 if (state & NK_WIDGET_STATE_HOVER) { | |
14452 background = &style->hover; | |
14453 cursor = &style->cursor_hover; | |
14454 text.text = style->text_hover; | |
14455 } else if (state & NK_WIDGET_STATE_ACTIVED) { | |
14456 background = &style->hover; | |
14457 cursor = &style->cursor_hover; | |
14458 text.text = style->text_active; | |
14459 } else { | |
14460 background = &style->normal; | |
14461 cursor = &style->cursor_normal; | |
14462 text.text = style->text_normal; | |
14463 } | |
14464 | |
14465 /* draw background and cursor */ | |
14466 if (background->type == NK_STYLE_ITEM_COLOR) { | |
14467 nk_fill_circle(out, *selector, style->border_color); | |
14468 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); | |
14469 } else nk_draw_image(out, *selector, &background->data.image, nk_white); | |
14470 if (active) { | |
14471 if (cursor->type == NK_STYLE_ITEM_IMAGE) | |
14472 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); | |
14473 else nk_fill_circle(out, *cursors, cursor->data.color); | |
14474 } | |
14475 | |
14476 text.padding.x = 0; | |
14477 text.padding.y = 0; | |
14478 text.background = style->text_background; | |
14479 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); | |
14480 } | |
14481 | |
14482 NK_INTERN int | |
14483 nk_do_toggle(nk_flags *state, | |
14484 struct nk_command_buffer *out, struct nk_rect r, | |
14485 int *active, const char *str, int len, enum nk_toggle_type type, | |
14486 const struct nk_style_toggle *style, const struct nk_input *in, | |
14487 const struct nk_user_font *font) | |
14488 { | |
14489 int was_active; | |
14490 struct nk_rect bounds; | |
14491 struct nk_rect select; | |
14492 struct nk_rect cursor; | |
14493 struct nk_rect label; | |
14494 | |
14495 NK_ASSERT(style); | |
14496 NK_ASSERT(out); | |
14497 NK_ASSERT(font); | |
14498 if (!out || !style || !font || !active) | |
14499 return 0; | |
14500 | |
14501 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); | |
14502 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); | |
14503 | |
14504 /* add additional touch padding for touch screen devices */ | |
14505 bounds.x = r.x - style->touch_padding.x; | |
14506 bounds.y = r.y - style->touch_padding.y; | |
14507 bounds.w = r.w + 2 * style->touch_padding.x; | |
14508 bounds.h = r.h + 2 * style->touch_padding.y; | |
14509 | |
14510 /* calculate the selector space */ | |
14511 select.w = font->height; | |
14512 select.h = select.w; | |
14513 select.y = r.y + r.h/2.0f - select.h/2.0f; | |
14514 select.x = r.x; | |
14515 | |
14516 /* calculate the bounds of the cursor inside the selector */ | |
14517 cursor.x = select.x + style->padding.x + style->border; | |
14518 cursor.y = select.y + style->padding.y + style->border; | |
14519 cursor.w = select.w - (2 * style->padding.x + 2 * style->border); | |
14520 cursor.h = select.h - (2 * style->padding.y + 2 * style->border); | |
14521 | |
14522 /* label behind the selector */ | |
14523 label.x = select.x + select.w + style->spacing; | |
14524 label.y = select.y; | |
14525 label.w = NK_MAX(r.x + r.w, label.x) - label.x; | |
14526 label.h = select.w; | |
14527 | |
14528 /* update selector */ | |
14529 was_active = *active; | |
14530 *active = nk_toggle_behavior(in, bounds, state, *active); | |
14531 | |
14532 /* draw selector */ | |
14533 if (style->draw_begin) | |
14534 style->draw_begin(out, style->userdata); | |
14535 if (type == NK_TOGGLE_CHECK) { | |
14536 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); | |
14537 } else { | |
14538 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); | |
14539 } | |
14540 if (style->draw_end) | |
14541 style->draw_end(out, style->userdata); | |
14542 return (was_active != *active); | |
14543 } | |
14544 | |
14545 /* =============================================================== | |
14546 * | |
14547 * SELECTABLE | |
14548 * | |
14549 * ===============================================================*/ | |
14550 NK_INTERN void | |
14551 nk_draw_selectable(struct nk_command_buffer *out, | |
14552 nk_flags state, const struct nk_style_selectable *style, int active, | |
14553 const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, | |
14554 const char *string, int len, nk_flags align, const struct nk_user_font *font) | |
14555 { | |
14556 const struct nk_style_item *background; | |
14557 struct nk_text text; | |
14558 text.padding = style->padding; | |
14559 | |
14560 /* select correct colors/images */ | |
14561 if (!active) { | |
14562 if (state & NK_WIDGET_STATE_ACTIVED) { | |
14563 background = &style->pressed; | |
14564 text.text = style->text_pressed; | |
14565 } else if (state & NK_WIDGET_STATE_HOVER) { | |
14566 background = &style->hover; | |
14567 text.text = style->text_hover; | |
14568 } else { | |
14569 background = &style->normal; | |
14570 text.text = style->text_normal; | |
14571 } | |
14572 } else { | |
14573 if (state & NK_WIDGET_STATE_ACTIVED) { | |
14574 background = &style->pressed_active; | |
14575 text.text = style->text_pressed_active; | |
14576 } else if (state & NK_WIDGET_STATE_HOVER) { | |
14577 background = &style->hover_active; | |
14578 text.text = style->text_hover_active; | |
14579 } else { | |
14580 background = &style->normal_active; | |
14581 text.text = style->text_normal_active; | |
14582 } | |
14583 } | |
14584 | |
14585 | |
14586 /* draw selectable background and text */ | |
14587 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
14588 nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
14589 text.background = nk_rgba(0,0,0,0); | |
14590 } else { | |
14591 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
14592 text.background = background->data.color; | |
14593 } | |
14594 if (img && icon) nk_draw_image(out, *icon, img, nk_white); | |
14595 nk_widget_text(out, *bounds, string, len, &text, align, font); | |
14596 } | |
14597 | |
14598 NK_INTERN int | |
14599 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, | |
14600 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, | |
14601 const struct nk_style_selectable *style, const struct nk_input *in, | |
14602 const struct nk_user_font *font) | |
14603 { | |
14604 int old_value; | |
14605 struct nk_rect touch; | |
14606 | |
14607 NK_ASSERT(state); | |
14608 NK_ASSERT(out); | |
14609 NK_ASSERT(str); | |
14610 NK_ASSERT(len); | |
14611 NK_ASSERT(value); | |
14612 NK_ASSERT(style); | |
14613 NK_ASSERT(font); | |
14614 | |
14615 if (!state || !out || !str || !len || !value || !style || !font) return 0; | |
14616 old_value = *value; | |
14617 | |
14618 /* remove padding */ | |
14619 touch.x = bounds.x - style->touch_padding.x; | |
14620 touch.y = bounds.y - style->touch_padding.y; | |
14621 touch.w = bounds.w + style->touch_padding.x * 2; | |
14622 touch.h = bounds.h + style->touch_padding.y * 2; | |
14623 | |
14624 /* update button */ | |
14625 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) | |
14626 *value = !(*value); | |
14627 | |
14628 /* draw selectable */ | |
14629 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14630 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font); | |
14631 if (style->draw_end) style->draw_end(out, style->userdata); | |
14632 return old_value != *value; | |
14633 } | |
14634 | |
14635 NK_INTERN int | |
14636 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, | |
14637 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, | |
14638 const struct nk_image *img, const struct nk_style_selectable *style, | |
14639 const struct nk_input *in, const struct nk_user_font *font) | |
14640 { | |
14641 int old_value; | |
14642 struct nk_rect touch; | |
14643 struct nk_rect icon; | |
14644 | |
14645 NK_ASSERT(state); | |
14646 NK_ASSERT(out); | |
14647 NK_ASSERT(str); | |
14648 NK_ASSERT(len); | |
14649 NK_ASSERT(value); | |
14650 NK_ASSERT(style); | |
14651 NK_ASSERT(font); | |
14652 | |
14653 if (!state || !out || !str || !len || !value || !style || !font) return 0; | |
14654 old_value = *value; | |
14655 | |
14656 /* toggle behavior */ | |
14657 touch.x = bounds.x - style->touch_padding.x; | |
14658 touch.y = bounds.y - style->touch_padding.y; | |
14659 touch.w = bounds.w + style->touch_padding.x * 2; | |
14660 touch.h = bounds.h + style->touch_padding.y * 2; | |
14661 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) | |
14662 *value = !(*value); | |
14663 | |
14664 icon.y = bounds.y + style->padding.y; | |
14665 icon.w = icon.h = bounds.h - 2 * style->padding.y; | |
14666 if (align & NK_TEXT_ALIGN_LEFT) { | |
14667 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); | |
14668 icon.x = NK_MAX(icon.x, 0); | |
14669 } else icon.x = bounds.x + 2 * style->padding.x; | |
14670 | |
14671 icon.x += style->image_padding.x; | |
14672 icon.y += style->image_padding.y; | |
14673 icon.w -= 2 * style->image_padding.x; | |
14674 icon.h -= 2 * style->image_padding.y; | |
14675 | |
14676 /* draw selectable */ | |
14677 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14678 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font); | |
14679 if (style->draw_end) style->draw_end(out, style->userdata); | |
14680 return old_value != *value; | |
14681 } | |
14682 | |
14683 | |
14684 /* =============================================================== | |
14685 * | |
14686 * SLIDER | |
14687 * | |
14688 * ===============================================================*/ | |
14689 NK_INTERN float | |
14690 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, | |
14691 struct nk_rect *visual_cursor, struct nk_input *in, | |
14692 struct nk_rect bounds, float slider_min, float slider_max, float slider_value, | |
14693 float slider_step, float slider_steps) | |
14694 { | |
14695 int left_mouse_down; | |
14696 int left_mouse_click_in_cursor; | |
14697 | |
14698 /* check if visual cursor is being dragged */ | |
14699 nk_widget_state_reset(state); | |
14700 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; | |
14701 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, | |
14702 NK_BUTTON_LEFT, *visual_cursor, nk_true); | |
14703 | |
14704 if (left_mouse_down && left_mouse_click_in_cursor) | |
14705 { | |
14706 float ratio = 0; | |
14707 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f); | |
14708 const float pxstep = bounds.w / slider_steps; | |
14709 | |
14710 /* only update value if the next slider step is reached */ | |
14711 *state = NK_WIDGET_STATE_ACTIVE; | |
14712 if (NK_ABS(d) >= pxstep) { | |
14713 const float steps = (float)((int)(NK_ABS(d) / pxstep)); | |
14714 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); | |
14715 slider_value = NK_CLAMP(slider_min, slider_value, slider_max); | |
14716 ratio = (slider_value - slider_min)/slider_step; | |
14717 logical_cursor->x = bounds.x + (logical_cursor->w * ratio); | |
14718 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x; | |
14719 } | |
14720 } | |
14721 | |
14722 /* slider widget state */ | |
14723 if (nk_input_is_mouse_hovering_rect(in, bounds)) | |
14724 *state = NK_WIDGET_STATE_HOVERED; | |
14725 if (*state & NK_WIDGET_STATE_HOVER && | |
14726 !nk_input_is_mouse_prev_hovering_rect(in, bounds)) | |
14727 *state |= NK_WIDGET_STATE_ENTERED; | |
14728 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) | |
14729 *state |= NK_WIDGET_STATE_LEFT; | |
14730 return slider_value; | |
14731 } | |
14732 | |
14733 NK_INTERN void | |
14734 nk_draw_slider(struct nk_command_buffer *out, nk_flags state, | |
14735 const struct nk_style_slider *style, const struct nk_rect *bounds, | |
14736 const struct nk_rect *visual_cursor, float min, float value, float max) | |
14737 { | |
14738 struct nk_rect fill; | |
14739 struct nk_rect bar; | |
14740 const struct nk_style_item *background; | |
14741 | |
14742 /* select correct slider images/colors */ | |
14743 struct nk_color bar_color; | |
14744 const struct nk_style_item *cursor; | |
14745 | |
14746 NK_UNUSED(min); | |
14747 NK_UNUSED(max); | |
14748 NK_UNUSED(value); | |
14749 | |
14750 if (state & NK_WIDGET_STATE_ACTIVED) { | |
14751 background = &style->active; | |
14752 bar_color = style->bar_active; | |
14753 cursor = &style->cursor_active; | |
14754 } else if (state & NK_WIDGET_STATE_HOVER) { | |
14755 background = &style->hover; | |
14756 bar_color = style->bar_hover; | |
14757 cursor = &style->cursor_hover; | |
14758 } else { | |
14759 background = &style->normal; | |
14760 bar_color = style->bar_normal; | |
14761 cursor = &style->cursor_normal; | |
14762 } | |
14763 | |
14764 /* calculate slider background bar */ | |
14765 bar.x = bounds->x; | |
14766 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; | |
14767 bar.w = bounds->w; | |
14768 bar.h = bounds->h/6; | |
14769 | |
14770 /* filled background bar style */ | |
14771 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; | |
14772 fill.x = bar.x; | |
14773 fill.y = bar.y; | |
14774 fill.h = bar.h; | |
14775 | |
14776 /* draw background */ | |
14777 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
14778 nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
14779 } else { | |
14780 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
14781 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); | |
14782 } | |
14783 | |
14784 /* draw slider bar */ | |
14785 nk_fill_rect(out, bar, style->rounding, bar_color); | |
14786 nk_fill_rect(out, fill, style->rounding, style->bar_filled); | |
14787 | |
14788 /* draw cursor */ | |
14789 if (cursor->type == NK_STYLE_ITEM_IMAGE) | |
14790 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); | |
14791 else nk_fill_circle(out, *visual_cursor, cursor->data.color); | |
14792 } | |
14793 | |
14794 NK_INTERN float | |
14795 nk_do_slider(nk_flags *state, | |
14796 struct nk_command_buffer *out, struct nk_rect bounds, | |
14797 float min, float val, float max, float step, | |
14798 const struct nk_style_slider *style, struct nk_input *in, | |
14799 const struct nk_user_font *font) | |
14800 { | |
14801 float slider_range; | |
14802 float slider_min; | |
14803 float slider_max; | |
14804 float slider_value; | |
14805 float slider_steps; | |
14806 float cursor_offset; | |
14807 | |
14808 struct nk_rect visual_cursor; | |
14809 struct nk_rect logical_cursor; | |
14810 | |
14811 NK_ASSERT(style); | |
14812 NK_ASSERT(out); | |
14813 if (!out || !style) | |
14814 return 0; | |
14815 | |
14816 /* remove padding from slider bounds */ | |
14817 bounds.x = bounds.x + style->padding.x; | |
14818 bounds.y = bounds.y + style->padding.y; | |
14819 bounds.h = NK_MAX(bounds.h, 2*style->padding.y); | |
14820 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); | |
14821 bounds.w -= 2 * style->padding.x; | |
14822 bounds.h -= 2 * style->padding.y; | |
14823 | |
14824 /* optional buttons */ | |
14825 if (style->show_buttons) { | |
14826 nk_flags ws; | |
14827 struct nk_rect button; | |
14828 button.y = bounds.y; | |
14829 button.w = bounds.h; | |
14830 button.h = bounds.h; | |
14831 | |
14832 /* decrement button */ | |
14833 button.x = bounds.x; | |
14834 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, | |
14835 &style->dec_button, in, font)) | |
14836 val -= step; | |
14837 | |
14838 /* increment button */ | |
14839 button.x = (bounds.x + bounds.w) - button.w; | |
14840 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, | |
14841 &style->inc_button, in, font)) | |
14842 val += step; | |
14843 | |
14844 bounds.x = bounds.x + button.w + style->spacing.x; | |
14845 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); | |
14846 } | |
14847 | |
14848 /* remove one cursor size to support visual cursor */ | |
14849 bounds.x += style->cursor_size.x*0.5f; | |
14850 bounds.w -= style->cursor_size.x; | |
14851 | |
14852 /* make sure the provided values are correct */ | |
14853 slider_max = NK_MAX(min, max); | |
14854 slider_min = NK_MIN(min, max); | |
14855 slider_value = NK_CLAMP(slider_min, val, slider_max); | |
14856 slider_range = slider_max - slider_min; | |
14857 slider_steps = slider_range / step; | |
14858 cursor_offset = (slider_value - slider_min) / step; | |
14859 | |
14860 /* calculate cursor | |
14861 Basically you have two cursors. One for visual representation and interaction | |
14862 and one for updating the actual cursor value. */ | |
14863 logical_cursor.h = bounds.h; | |
14864 logical_cursor.w = bounds.w / slider_steps; | |
14865 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); | |
14866 logical_cursor.y = bounds.y; | |
14867 | |
14868 visual_cursor.h = style->cursor_size.y; | |
14869 visual_cursor.w = style->cursor_size.x; | |
14870 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; | |
14871 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; | |
14872 | |
14873 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, | |
14874 in, bounds, slider_min, slider_max, slider_value, step, slider_steps); | |
14875 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; | |
14876 | |
14877 /* draw slider */ | |
14878 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14879 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); | |
14880 if (style->draw_end) style->draw_end(out, style->userdata); | |
14881 return slider_value; | |
14882 } | |
14883 | |
14884 /* =============================================================== | |
14885 * | |
14886 * PROGRESSBAR | |
14887 * | |
14888 * ===============================================================*/ | |
14889 NK_INTERN nk_size | |
14890 nk_progress_behavior(nk_flags *state, const struct nk_input *in, | |
14891 struct nk_rect r, nk_size max, nk_size value, int modifiable) | |
14892 { | |
14893 nk_widget_state_reset(state); | |
14894 if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) { | |
14895 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; | |
14896 int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, | |
14897 NK_BUTTON_LEFT, r, nk_true); | |
14898 | |
14899 if (left_mouse_down && left_mouse_click_in_cursor) { | |
14900 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w; | |
14901 value = (nk_size)NK_MAX(0,((float)max * ratio)); | |
14902 *state = NK_WIDGET_STATE_ACTIVE; | |
14903 } else *state = NK_WIDGET_STATE_HOVERED; | |
14904 } | |
14905 | |
14906 /* set progressbar widget state */ | |
14907 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) | |
14908 *state |= NK_WIDGET_STATE_ENTERED; | |
14909 else if (nk_input_is_mouse_prev_hovering_rect(in, r)) | |
14910 *state |= NK_WIDGET_STATE_LEFT; | |
14911 | |
14912 if (!max) return value; | |
14913 value = NK_MIN(value, max); | |
14914 return value; | |
14915 } | |
14916 | |
14917 NK_INTERN void | |
14918 nk_draw_progress(struct nk_command_buffer *out, nk_flags state, | |
14919 const struct nk_style_progress *style, const struct nk_rect *bounds, | |
14920 const struct nk_rect *scursor, nk_size value, nk_size max) | |
14921 { | |
14922 const struct nk_style_item *background; | |
14923 const struct nk_style_item *cursor; | |
14924 | |
14925 NK_UNUSED(max); | |
14926 NK_UNUSED(value); | |
14927 | |
14928 /* select correct colors/images to draw */ | |
14929 if (state & NK_WIDGET_STATE_ACTIVED) { | |
14930 background = &style->active; | |
14931 cursor = &style->cursor_active; | |
14932 } else if (state & NK_WIDGET_STATE_HOVER){ | |
14933 background = &style->hover; | |
14934 cursor = &style->cursor_hover; | |
14935 } else { | |
14936 background = &style->normal; | |
14937 cursor = &style->cursor_normal; | |
14938 } | |
14939 | |
14940 /* draw background */ | |
14941 if (background->type == NK_STYLE_ITEM_COLOR) { | |
14942 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
14943 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); | |
14944 } else nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
14945 | |
14946 /* draw cursor */ | |
14947 if (cursor->type == NK_STYLE_ITEM_COLOR) { | |
14948 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); | |
14949 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); | |
14950 } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white); | |
14951 } | |
14952 | |
14953 NK_INTERN nk_size | |
14954 nk_do_progress(nk_flags *state, | |
14955 struct nk_command_buffer *out, struct nk_rect bounds, | |
14956 nk_size value, nk_size max, int modifiable, | |
14957 const struct nk_style_progress *style, const struct nk_input *in) | |
14958 { | |
14959 float prog_scale; | |
14960 nk_size prog_value; | |
14961 struct nk_rect cursor; | |
14962 | |
14963 NK_ASSERT(style); | |
14964 NK_ASSERT(out); | |
14965 if (!out || !style) return 0; | |
14966 | |
14967 /* calculate progressbar cursor */ | |
14968 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); | |
14969 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); | |
14970 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); | |
14971 prog_scale = (float)value / (float)max; | |
14972 cursor.w = (bounds.w - 2) * prog_scale; | |
14973 | |
14974 /* update progressbar */ | |
14975 prog_value = NK_MIN(value, max); | |
14976 prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable); | |
14977 | |
14978 /* draw progressbar */ | |
14979 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
14980 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); | |
14981 if (style->draw_end) style->draw_end(out, style->userdata); | |
14982 return prog_value; | |
14983 } | |
14984 | |
14985 /* =============================================================== | |
14986 * | |
14987 * SCROLLBAR | |
14988 * | |
14989 * ===============================================================*/ | |
14990 NK_INTERN float | |
14991 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, | |
14992 int has_scrolling, const struct nk_rect *scroll, | |
14993 const struct nk_rect *cursor, const struct nk_rect *empty0, | |
14994 const struct nk_rect *empty1, float scroll_offset, | |
14995 float target, float scroll_step, enum nk_orientation o) | |
14996 { | |
14997 nk_flags ws = 0; | |
14998 int left_mouse_down; | |
14999 int left_mouse_click_in_cursor; | |
15000 float scroll_delta; | |
15001 | |
15002 nk_widget_state_reset(state); | |
15003 if (!in) return scroll_offset; | |
15004 | |
15005 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; | |
15006 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, | |
15007 NK_BUTTON_LEFT, *cursor, nk_true); | |
15008 if (nk_input_is_mouse_hovering_rect(in, *scroll)) | |
15009 *state = NK_WIDGET_STATE_HOVERED; | |
15010 | |
15011 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; | |
15012 if (left_mouse_down && left_mouse_click_in_cursor) { | |
15013 /* update cursor by mouse dragging */ | |
15014 float pixel, delta; | |
15015 *state = NK_WIDGET_STATE_ACTIVE; | |
15016 if (o == NK_VERTICAL) { | |
15017 float cursor_y; | |
15018 pixel = in->mouse.delta.y; | |
15019 delta = (pixel / scroll->h) * target; | |
15020 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); | |
15021 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); | |
15022 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; | |
15023 } else { | |
15024 float cursor_x; | |
15025 pixel = in->mouse.delta.x; | |
15026 delta = (pixel / scroll->w) * target; | |
15027 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); | |
15028 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); | |
15029 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; | |
15030 } | |
15031 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| | |
15032 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { | |
15033 /* scroll page up by click on empty space or shortcut */ | |
15034 if (o == NK_VERTICAL) | |
15035 scroll_offset = NK_MAX(0, scroll_offset - scroll->h); | |
15036 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); | |
15037 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || | |
15038 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { | |
15039 /* scroll page down by click on empty space or shortcut */ | |
15040 if (o == NK_VERTICAL) | |
15041 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); | |
15042 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); | |
15043 } else if (has_scrolling) { | |
15044 if ((scroll_delta < 0 || (scroll_delta > 0))) { | |
15045 /* update cursor by mouse scrolling */ | |
15046 scroll_offset = scroll_offset + scroll_step * (-scroll_delta); | |
15047 if (o == NK_VERTICAL) | |
15048 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); | |
15049 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); | |
15050 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { | |
15051 /* update cursor to the beginning */ | |
15052 if (o == NK_VERTICAL) scroll_offset = 0; | |
15053 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { | |
15054 /* update cursor to the end */ | |
15055 if (o == NK_VERTICAL) scroll_offset = target - scroll->h; | |
15056 } | |
15057 } | |
15058 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) | |
15059 *state |= NK_WIDGET_STATE_ENTERED; | |
15060 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) | |
15061 *state |= NK_WIDGET_STATE_LEFT; | |
15062 return scroll_offset; | |
15063 } | |
15064 | |
15065 NK_INTERN void | |
15066 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, | |
15067 const struct nk_style_scrollbar *style, const struct nk_rect *bounds, | |
15068 const struct nk_rect *scroll) | |
15069 { | |
15070 const struct nk_style_item *background; | |
15071 const struct nk_style_item *cursor; | |
15072 | |
15073 /* select correct colors/images to draw */ | |
15074 if (state & NK_WIDGET_STATE_ACTIVED) { | |
15075 background = &style->active; | |
15076 cursor = &style->cursor_active; | |
15077 } else if (state & NK_WIDGET_STATE_HOVER) { | |
15078 background = &style->hover; | |
15079 cursor = &style->cursor_hover; | |
15080 } else { | |
15081 background = &style->normal; | |
15082 cursor = &style->cursor_normal; | |
15083 } | |
15084 | |
15085 /* draw background */ | |
15086 if (background->type == NK_STYLE_ITEM_COLOR) { | |
15087 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
15088 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); | |
15089 } else { | |
15090 nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
15091 } | |
15092 | |
15093 /* draw cursor */ | |
15094 if (background->type == NK_STYLE_ITEM_COLOR) { | |
15095 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); | |
15096 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); | |
15097 } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); | |
15098 } | |
15099 | |
15100 NK_INTERN float | |
15101 nk_do_scrollbarv(nk_flags *state, | |
15102 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, | |
15103 float offset, float target, float step, float button_pixel_inc, | |
15104 const struct nk_style_scrollbar *style, struct nk_input *in, | |
15105 const struct nk_user_font *font) | |
15106 { | |
15107 struct nk_rect empty_north; | |
15108 struct nk_rect empty_south; | |
15109 struct nk_rect cursor; | |
15110 | |
15111 float scroll_step; | |
15112 float scroll_offset; | |
15113 float scroll_off; | |
15114 float scroll_ratio; | |
15115 | |
15116 NK_ASSERT(out); | |
15117 NK_ASSERT(style); | |
15118 NK_ASSERT(state); | |
15119 if (!out || !style) return 0; | |
15120 | |
15121 scroll.w = NK_MAX(scroll.w, 1); | |
15122 scroll.h = NK_MAX(scroll.h, 0); | |
15123 if (target <= scroll.h) return 0; | |
15124 | |
15125 /* optional scrollbar buttons */ | |
15126 if (style->show_buttons) { | |
15127 nk_flags ws; | |
15128 float scroll_h; | |
15129 struct nk_rect button; | |
15130 | |
15131 button.x = scroll.x; | |
15132 button.w = scroll.w; | |
15133 button.h = scroll.w; | |
15134 | |
15135 scroll_h = NK_MAX(scroll.h - 2 * button.h,0); | |
15136 scroll_step = NK_MIN(step, button_pixel_inc); | |
15137 | |
15138 /* decrement button */ | |
15139 button.y = scroll.y; | |
15140 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, | |
15141 NK_BUTTON_REPEATER, &style->dec_button, in, font)) | |
15142 offset = offset - scroll_step; | |
15143 | |
15144 /* increment button */ | |
15145 button.y = scroll.y + scroll.h - button.h; | |
15146 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, | |
15147 NK_BUTTON_REPEATER, &style->inc_button, in, font)) | |
15148 offset = offset + scroll_step; | |
15149 | |
15150 scroll.y = scroll.y + button.h; | |
15151 scroll.h = scroll_h; | |
15152 } | |
15153 | |
15154 /* calculate scrollbar constants */ | |
15155 scroll_step = NK_MIN(step, scroll.h); | |
15156 scroll_offset = NK_CLAMP(0, offset, target - scroll.h); | |
15157 scroll_ratio = scroll.h / target; | |
15158 scroll_off = scroll_offset / target; | |
15159 | |
15160 /* calculate scrollbar cursor bounds */ | |
15161 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0); | |
15162 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; | |
15163 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); | |
15164 cursor.x = scroll.x + style->border + style->padding.x; | |
15165 | |
15166 /* calculate empty space around cursor */ | |
15167 empty_north.x = scroll.x; | |
15168 empty_north.y = scroll.y; | |
15169 empty_north.w = scroll.w; | |
15170 empty_north.h = NK_MAX(cursor.y - scroll.y, 0); | |
15171 | |
15172 empty_south.x = scroll.x; | |
15173 empty_south.y = cursor.y + cursor.h; | |
15174 empty_south.w = scroll.w; | |
15175 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0); | |
15176 | |
15177 /* update scrollbar */ | |
15178 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, | |
15179 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); | |
15180 scroll_off = scroll_offset / target; | |
15181 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; | |
15182 | |
15183 /* draw scrollbar */ | |
15184 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
15185 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); | |
15186 if (style->draw_end) style->draw_end(out, style->userdata); | |
15187 return scroll_offset; | |
15188 } | |
15189 | |
15190 NK_INTERN float | |
15191 nk_do_scrollbarh(nk_flags *state, | |
15192 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, | |
15193 float offset, float target, float step, float button_pixel_inc, | |
15194 const struct nk_style_scrollbar *style, struct nk_input *in, | |
15195 const struct nk_user_font *font) | |
15196 { | |
15197 struct nk_rect cursor; | |
15198 struct nk_rect empty_west; | |
15199 struct nk_rect empty_east; | |
15200 | |
15201 float scroll_step; | |
15202 float scroll_offset; | |
15203 float scroll_off; | |
15204 float scroll_ratio; | |
15205 | |
15206 NK_ASSERT(out); | |
15207 NK_ASSERT(style); | |
15208 if (!out || !style) return 0; | |
15209 | |
15210 /* scrollbar background */ | |
15211 scroll.h = NK_MAX(scroll.h, 1); | |
15212 scroll.w = NK_MAX(scroll.w, 2 * scroll.h); | |
15213 if (target <= scroll.w) return 0; | |
15214 | |
15215 /* optional scrollbar buttons */ | |
15216 if (style->show_buttons) { | |
15217 nk_flags ws; | |
15218 float scroll_w; | |
15219 struct nk_rect button; | |
15220 button.y = scroll.y; | |
15221 button.w = scroll.h; | |
15222 button.h = scroll.h; | |
15223 | |
15224 scroll_w = scroll.w - 2 * button.w; | |
15225 scroll_step = NK_MIN(step, button_pixel_inc); | |
15226 | |
15227 /* decrement button */ | |
15228 button.x = scroll.x; | |
15229 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, | |
15230 NK_BUTTON_REPEATER, &style->dec_button, in, font)) | |
15231 offset = offset - scroll_step; | |
15232 | |
15233 /* increment button */ | |
15234 button.x = scroll.x + scroll.w - button.w; | |
15235 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, | |
15236 NK_BUTTON_REPEATER, &style->inc_button, in, font)) | |
15237 offset = offset + scroll_step; | |
15238 | |
15239 scroll.x = scroll.x + button.w; | |
15240 scroll.w = scroll_w; | |
15241 } | |
15242 | |
15243 /* calculate scrollbar constants */ | |
15244 scroll_step = NK_MIN(step, scroll.w); | |
15245 scroll_offset = NK_CLAMP(0, offset, target - scroll.w); | |
15246 scroll_ratio = scroll.w / target; | |
15247 scroll_off = scroll_offset / target; | |
15248 | |
15249 /* calculate cursor bounds */ | |
15250 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); | |
15251 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; | |
15252 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); | |
15253 cursor.y = scroll.y + style->border + style->padding.y; | |
15254 | |
15255 /* calculate empty space around cursor */ | |
15256 empty_west.x = scroll.x; | |
15257 empty_west.y = scroll.y; | |
15258 empty_west.w = cursor.x - scroll.x; | |
15259 empty_west.h = scroll.h; | |
15260 | |
15261 empty_east.x = cursor.x + cursor.w; | |
15262 empty_east.y = scroll.y; | |
15263 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); | |
15264 empty_east.h = scroll.h; | |
15265 | |
15266 /* update scrollbar */ | |
15267 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, | |
15268 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); | |
15269 scroll_off = scroll_offset / target; | |
15270 cursor.x = scroll.x + (scroll_off * scroll.w); | |
15271 | |
15272 /* draw scrollbar */ | |
15273 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
15274 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); | |
15275 if (style->draw_end) style->draw_end(out, style->userdata); | |
15276 return scroll_offset; | |
15277 } | |
15278 | |
15279 /* =============================================================== | |
15280 * | |
15281 * FILTER | |
15282 * | |
15283 * ===============================================================*/ | |
15284 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) | |
15285 {(void)unicode;NK_UNUSED(box);return nk_true;} | |
15286 | |
15287 NK_API int | |
15288 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) | |
15289 { | |
15290 NK_UNUSED(box); | |
15291 if (unicode > 128) return nk_false; | |
15292 else return nk_true; | |
15293 } | |
15294 | |
15295 NK_API int | |
15296 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) | |
15297 { | |
15298 NK_UNUSED(box); | |
15299 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') | |
15300 return nk_false; | |
15301 else return nk_true; | |
15302 } | |
15303 | |
15304 NK_API int | |
15305 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) | |
15306 { | |
15307 NK_UNUSED(box); | |
15308 if ((unicode < '0' || unicode > '9') && unicode != '-') | |
15309 return nk_false; | |
15310 else return nk_true; | |
15311 } | |
15312 | |
15313 NK_API int | |
15314 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) | |
15315 { | |
15316 NK_UNUSED(box); | |
15317 if ((unicode < '0' || unicode > '9') && | |
15318 (unicode < 'a' || unicode > 'f') && | |
15319 (unicode < 'A' || unicode > 'F')) | |
15320 return nk_false; | |
15321 else return nk_true; | |
15322 } | |
15323 | |
15324 NK_API int | |
15325 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) | |
15326 { | |
15327 NK_UNUSED(box); | |
15328 if (unicode < '0' || unicode > '7') | |
15329 return nk_false; | |
15330 else return nk_true; | |
15331 } | |
15332 | |
15333 NK_API int | |
15334 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) | |
15335 { | |
15336 NK_UNUSED(box); | |
15337 if (unicode != '0' && unicode != '1') | |
15338 return nk_false; | |
15339 else return nk_true; | |
15340 } | |
15341 | |
15342 /* =============================================================== | |
15343 * | |
15344 * EDIT | |
15345 * | |
15346 * ===============================================================*/ | |
15347 NK_INTERN void | |
15348 nk_edit_draw_text(struct nk_command_buffer *out, | |
15349 const struct nk_style_edit *style, float pos_x, float pos_y, | |
15350 float x_offset, const char *text, int byte_len, float row_height, | |
15351 const struct nk_user_font *font, struct nk_color background, | |
15352 struct nk_color foreground, int is_selected) | |
15353 { | |
15354 NK_ASSERT(out); | |
15355 NK_ASSERT(font); | |
15356 NK_ASSERT(style); | |
15357 if (!text || !byte_len || !out || !style) return; | |
15358 | |
15359 {int glyph_len = 0; | |
15360 nk_rune unicode = 0; | |
15361 int text_len = 0; | |
15362 float line_width = 0; | |
15363 float glyph_width; | |
15364 const char *line = text; | |
15365 float line_offset = 0; | |
15366 int line_count = 0; | |
15367 | |
15368 struct nk_text txt; | |
15369 txt.padding = nk_vec2(0,0); | |
15370 txt.background = background; | |
15371 txt.text = foreground; | |
15372 | |
15373 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); | |
15374 if (!glyph_len) return; | |
15375 while ((text_len < byte_len) && glyph_len) | |
15376 { | |
15377 if (unicode == '\n') { | |
15378 /* new line separator so draw previous line */ | |
15379 struct nk_rect label; | |
15380 label.y = pos_y + line_offset; | |
15381 label.h = row_height; | |
15382 label.w = line_width; | |
15383 label.x = pos_x; | |
15384 if (!line_count) | |
15385 label.x += x_offset; | |
15386 | |
15387 if (is_selected) /* selection needs to draw different background color */ | |
15388 nk_fill_rect(out, label, 0, background); | |
15389 nk_widget_text(out, label, line, (int)((text + text_len) - line), | |
15390 &txt, NK_TEXT_CENTERED, font); | |
15391 | |
15392 text_len++; | |
15393 line_count++; | |
15394 line_width = 0; | |
15395 line = text + text_len; | |
15396 line_offset += row_height; | |
15397 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); | |
15398 continue; | |
15399 } | |
15400 if (unicode == '\r') { | |
15401 text_len++; | |
15402 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); | |
15403 continue; | |
15404 } | |
15405 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); | |
15406 line_width += (float)glyph_width; | |
15407 text_len += glyph_len; | |
15408 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); | |
15409 continue; | |
15410 } | |
15411 if (line_width > 0) { | |
15412 /* draw last line */ | |
15413 struct nk_rect label; | |
15414 label.y = pos_y + line_offset; | |
15415 label.h = row_height; | |
15416 label.w = line_width; | |
15417 label.x = pos_x; | |
15418 if (!line_count) | |
15419 label.x += x_offset; | |
15420 | |
15421 if (is_selected) | |
15422 nk_fill_rect(out, label, 0, background); | |
15423 nk_widget_text(out, label, line, (int)((text + text_len) - line), | |
15424 &txt, NK_TEXT_LEFT, font); | |
15425 }} | |
15426 } | |
15427 | |
15428 NK_INTERN nk_flags | |
15429 nk_do_edit(nk_flags *state, struct nk_command_buffer *out, | |
15430 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, | |
15431 struct nk_text_edit *edit, const struct nk_style_edit *style, | |
15432 struct nk_input *in, const struct nk_user_font *font) | |
15433 { | |
15434 struct nk_rect area; | |
15435 nk_flags ret = 0; | |
15436 float row_height; | |
15437 char prev_state = 0; | |
15438 char is_hovered = 0; | |
15439 char select_all = 0; | |
15440 char cursor_follow = 0; | |
15441 struct nk_rect old_clip; | |
15442 struct nk_rect clip; | |
15443 | |
15444 NK_ASSERT(state); | |
15445 NK_ASSERT(out); | |
15446 NK_ASSERT(style); | |
15447 if (!state || !out || !style) | |
15448 return ret; | |
15449 | |
15450 /* visible text area calculation */ | |
15451 area.x = bounds.x + style->padding.x + style->border; | |
15452 area.y = bounds.y + style->padding.y + style->border; | |
15453 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); | |
15454 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); | |
15455 if (flags & NK_EDIT_MULTILINE) | |
15456 area.w = NK_MAX(0, area.w - style->scrollbar_size.x); | |
15457 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; | |
15458 | |
15459 /* calculate clipping rectangle */ | |
15460 old_clip = out->clip; | |
15461 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); | |
15462 | |
15463 /* update edit state */ | |
15464 prev_state = (char)edit->active; | |
15465 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); | |
15466 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { | |
15467 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, | |
15468 bounds.x, bounds.y, bounds.w, bounds.h); | |
15469 } | |
15470 | |
15471 /* (de)activate text editor */ | |
15472 if (!prev_state && edit->active) { | |
15473 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? | |
15474 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; | |
15475 nk_textedit_clear_state(edit, type, filter); | |
15476 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) | |
15477 edit->mode = NK_TEXT_EDIT_MODE_INSERT; | |
15478 if (flags & NK_EDIT_AUTO_SELECT) | |
15479 select_all = nk_true; | |
15480 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { | |
15481 edit->cursor = edit->string.len; | |
15482 in = 0; | |
15483 } | |
15484 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; | |
15485 if (flags & NK_EDIT_READ_ONLY) | |
15486 edit->mode = NK_TEXT_EDIT_MODE_VIEW; | |
15487 | |
15488 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; | |
15489 if (prev_state != edit->active) | |
15490 ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; | |
15491 | |
15492 /* handle user input */ | |
15493 if (edit->active && in) | |
15494 { | |
15495 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; | |
15496 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; | |
15497 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; | |
15498 | |
15499 /* mouse click handler */ | |
15500 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); | |
15501 if (select_all) { | |
15502 nk_textedit_select_all(edit); | |
15503 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && | |
15504 in->mouse.buttons[NK_BUTTON_LEFT].clicked) { | |
15505 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); | |
15506 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && | |
15507 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { | |
15508 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); | |
15509 cursor_follow = nk_true; | |
15510 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && | |
15511 in->mouse.buttons[NK_BUTTON_RIGHT].down) { | |
15512 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); | |
15513 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); | |
15514 cursor_follow = nk_true; | |
15515 } | |
15516 | |
15517 {int i; /* keyboard input */ | |
15518 int old_mode = edit->mode; | |
15519 for (i = 0; i < NK_KEY_MAX; ++i) { | |
15520 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ | |
15521 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { | |
15522 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); | |
15523 cursor_follow = nk_true; | |
15524 } | |
15525 } | |
15526 if (old_mode != edit->mode) { | |
15527 in->keyboard.text_len = 0; | |
15528 }} | |
15529 | |
15530 /* text input */ | |
15531 edit->filter = filter; | |
15532 if (in->keyboard.text_len) { | |
15533 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); | |
15534 cursor_follow = nk_true; | |
15535 in->keyboard.text_len = 0; | |
15536 } | |
15537 | |
15538 /* enter key handler */ | |
15539 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { | |
15540 cursor_follow = nk_true; | |
15541 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) | |
15542 nk_textedit_text(edit, "\n", 1); | |
15543 else if (flags & NK_EDIT_SIG_ENTER) | |
15544 ret |= NK_EDIT_COMMITED; | |
15545 else nk_textedit_text(edit, "\n", 1); | |
15546 } | |
15547 | |
15548 /* cut & copy handler */ | |
15549 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); | |
15550 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); | |
15551 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) | |
15552 { | |
15553 int glyph_len; | |
15554 nk_rune unicode; | |
15555 const char *text; | |
15556 int b = edit->select_start; | |
15557 int e = edit->select_end; | |
15558 | |
15559 int begin = NK_MIN(b, e); | |
15560 int end = NK_MAX(b, e); | |
15561 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); | |
15562 if (edit->clip.copy) | |
15563 edit->clip.copy(edit->clip.userdata, text, end - begin); | |
15564 if (cut && !(flags & NK_EDIT_READ_ONLY)){ | |
15565 nk_textedit_cut(edit); | |
15566 cursor_follow = nk_true; | |
15567 } | |
15568 }} | |
15569 | |
15570 /* paste handler */ | |
15571 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); | |
15572 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { | |
15573 edit->clip.paste(edit->clip.userdata, edit); | |
15574 cursor_follow = nk_true; | |
15575 }} | |
15576 | |
15577 /* tab handler */ | |
15578 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); | |
15579 if (tab && (flags & NK_EDIT_ALLOW_TAB)) { | |
15580 nk_textedit_text(edit, " ", 4); | |
15581 cursor_follow = nk_true; | |
15582 }} | |
15583 } | |
15584 | |
15585 /* set widget state */ | |
15586 if (edit->active) | |
15587 *state = NK_WIDGET_STATE_ACTIVE; | |
15588 else nk_widget_state_reset(state); | |
15589 | |
15590 if (is_hovered) | |
15591 *state |= NK_WIDGET_STATE_HOVERED; | |
15592 | |
15593 /* DRAW EDIT */ | |
15594 {const char *text = nk_str_get_const(&edit->string); | |
15595 int len = nk_str_len_char(&edit->string); | |
15596 | |
15597 {/* select background colors/images */ | |
15598 const struct nk_style_item *background; | |
15599 if (*state & NK_WIDGET_STATE_ACTIVED) | |
15600 background = &style->active; | |
15601 else if (*state & NK_WIDGET_STATE_HOVER) | |
15602 background = &style->hover; | |
15603 else background = &style->normal; | |
15604 | |
15605 /* draw background frame */ | |
15606 if (background->type == NK_STYLE_ITEM_COLOR) { | |
15607 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); | |
15608 nk_fill_rect(out, bounds, style->rounding, background->data.color); | |
15609 } else nk_draw_image(out, bounds, &background->data.image, nk_white);} | |
15610 | |
15611 area.w = NK_MAX(0, area.w - style->cursor_size); | |
15612 if (edit->active) | |
15613 { | |
15614 int total_lines = 1; | |
15615 struct nk_vec2 text_size = nk_vec2(0,0); | |
15616 | |
15617 /* text pointer positions */ | |
15618 const char *cursor_ptr = 0; | |
15619 const char *select_begin_ptr = 0; | |
15620 const char *select_end_ptr = 0; | |
15621 | |
15622 /* 2D pixel positions */ | |
15623 struct nk_vec2 cursor_pos = nk_vec2(0,0); | |
15624 struct nk_vec2 selection_offset_start = nk_vec2(0,0); | |
15625 struct nk_vec2 selection_offset_end = nk_vec2(0,0); | |
15626 | |
15627 int selection_begin = NK_MIN(edit->select_start, edit->select_end); | |
15628 int selection_end = NK_MAX(edit->select_start, edit->select_end); | |
15629 | |
15630 /* calculate total line count + total space + cursor/selection position */ | |
15631 float line_width = 0.0f; | |
15632 if (text && len) | |
15633 { | |
15634 /* utf8 encoding */ | |
15635 float glyph_width; | |
15636 int glyph_len = 0; | |
15637 nk_rune unicode = 0; | |
15638 int text_len = 0; | |
15639 int glyphs = 0; | |
15640 int row_begin = 0; | |
15641 | |
15642 glyph_len = nk_utf_decode(text, &unicode, len); | |
15643 glyph_width = font->width(font->userdata, font->height, text, glyph_len); | |
15644 line_width = 0; | |
15645 | |
15646 /* iterate all lines */ | |
15647 while ((text_len < len) && glyph_len) | |
15648 { | |
15649 /* set cursor 2D position and line */ | |
15650 if (!cursor_ptr && glyphs == edit->cursor) | |
15651 { | |
15652 int glyph_offset; | |
15653 struct nk_vec2 out_offset; | |
15654 struct nk_vec2 row_size; | |
15655 const char *remaining; | |
15656 | |
15657 /* calculate 2d position */ | |
15658 cursor_pos.y = (float)(total_lines-1) * row_height; | |
15659 row_size = nk_text_calculate_text_bounds(font, text+row_begin, | |
15660 text_len-row_begin, row_height, &remaining, | |
15661 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); | |
15662 cursor_pos.x = row_size.x; | |
15663 cursor_ptr = text + text_len; | |
15664 } | |
15665 | |
15666 /* set start selection 2D position and line */ | |
15667 if (!select_begin_ptr && edit->select_start != edit->select_end && | |
15668 glyphs == selection_begin) | |
15669 { | |
15670 int glyph_offset; | |
15671 struct nk_vec2 out_offset; | |
15672 struct nk_vec2 row_size; | |
15673 const char *remaining; | |
15674 | |
15675 /* calculate 2d position */ | |
15676 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; | |
15677 row_size = nk_text_calculate_text_bounds(font, text+row_begin, | |
15678 text_len-row_begin, row_height, &remaining, | |
15679 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); | |
15680 selection_offset_start.x = row_size.x; | |
15681 select_begin_ptr = text + text_len; | |
15682 } | |
15683 | |
15684 /* set end selection 2D position and line */ | |
15685 if (!select_end_ptr && edit->select_start != edit->select_end && | |
15686 glyphs == selection_end) | |
15687 { | |
15688 int glyph_offset; | |
15689 struct nk_vec2 out_offset; | |
15690 struct nk_vec2 row_size; | |
15691 const char *remaining; | |
15692 | |
15693 /* calculate 2d position */ | |
15694 selection_offset_end.y = (float)(total_lines-1) * row_height; | |
15695 row_size = nk_text_calculate_text_bounds(font, text+row_begin, | |
15696 text_len-row_begin, row_height, &remaining, | |
15697 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); | |
15698 selection_offset_end.x = row_size.x; | |
15699 select_end_ptr = text + text_len; | |
15700 } | |
15701 if (unicode == '\n') { | |
15702 text_size.x = NK_MAX(text_size.x, line_width); | |
15703 total_lines++; | |
15704 line_width = 0; | |
15705 text_len++; | |
15706 glyphs++; | |
15707 row_begin = text_len; | |
15708 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); | |
15709 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); | |
15710 continue; | |
15711 } | |
15712 | |
15713 glyphs++; | |
15714 text_len += glyph_len; | |
15715 line_width += (float)glyph_width; | |
15716 | |
15717 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); | |
15718 glyph_width = font->width(font->userdata, font->height, | |
15719 text+text_len, glyph_len); | |
15720 continue; | |
15721 } | |
15722 text_size.y = (float)total_lines * row_height; | |
15723 | |
15724 /* handle case when cursor is at end of text buffer */ | |
15725 if (!cursor_ptr && edit->cursor == edit->string.len) { | |
15726 cursor_pos.x = line_width; | |
15727 cursor_pos.y = text_size.y - row_height; | |
15728 } | |
15729 } | |
15730 { | |
15731 /* scrollbar */ | |
15732 if (cursor_follow) | |
15733 { | |
15734 /* update scrollbar to follow cursor */ | |
15735 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { | |
15736 /* horizontal scroll */ | |
15737 const float scroll_increment = area.w * 0.25f; | |
15738 if (cursor_pos.x < edit->scrollbar.x) | |
15739 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); | |
15740 if (cursor_pos.x >= edit->scrollbar.x + area.w) | |
15741 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x); | |
15742 } else edit->scrollbar.x = 0; | |
15743 | |
15744 if (flags & NK_EDIT_MULTILINE) { | |
15745 /* vertical scroll */ | |
15746 if (cursor_pos.y < edit->scrollbar.y) | |
15747 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); | |
15748 if (cursor_pos.y >= edit->scrollbar.y + area.h) | |
15749 edit->scrollbar.y = edit->scrollbar.y + row_height; | |
15750 } else edit->scrollbar.y = 0; | |
15751 } | |
15752 | |
15753 /* scrollbar widget */ | |
15754 if (flags & NK_EDIT_MULTILINE) | |
15755 { | |
15756 nk_flags ws; | |
15757 struct nk_rect scroll; | |
15758 float scroll_target; | |
15759 float scroll_offset; | |
15760 float scroll_step; | |
15761 float scroll_inc; | |
15762 | |
15763 scroll = area; | |
15764 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; | |
15765 scroll.w = style->scrollbar_size.x; | |
15766 | |
15767 scroll_offset = edit->scrollbar.y; | |
15768 scroll_step = scroll.h * 0.10f; | |
15769 scroll_inc = scroll.h * 0.01f; | |
15770 scroll_target = text_size.y; | |
15771 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, | |
15772 scroll_offset, scroll_target, scroll_step, scroll_inc, | |
15773 &style->scrollbar, in, font); | |
15774 } | |
15775 } | |
15776 | |
15777 /* draw text */ | |
15778 {struct nk_color background_color; | |
15779 struct nk_color text_color; | |
15780 struct nk_color sel_background_color; | |
15781 struct nk_color sel_text_color; | |
15782 struct nk_color cursor_color; | |
15783 struct nk_color cursor_text_color; | |
15784 const struct nk_style_item *background; | |
15785 nk_push_scissor(out, clip); | |
15786 | |
15787 /* select correct colors to draw */ | |
15788 if (*state & NK_WIDGET_STATE_ACTIVED) { | |
15789 background = &style->active; | |
15790 text_color = style->text_active; | |
15791 sel_text_color = style->selected_text_hover; | |
15792 sel_background_color = style->selected_hover; | |
15793 cursor_color = style->cursor_hover; | |
15794 cursor_text_color = style->cursor_text_hover; | |
15795 } else if (*state & NK_WIDGET_STATE_HOVER) { | |
15796 background = &style->hover; | |
15797 text_color = style->text_hover; | |
15798 sel_text_color = style->selected_text_hover; | |
15799 sel_background_color = style->selected_hover; | |
15800 cursor_text_color = style->cursor_text_hover; | |
15801 cursor_color = style->cursor_hover; | |
15802 } else { | |
15803 background = &style->normal; | |
15804 text_color = style->text_normal; | |
15805 sel_text_color = style->selected_text_normal; | |
15806 sel_background_color = style->selected_normal; | |
15807 cursor_color = style->cursor_normal; | |
15808 cursor_text_color = style->cursor_text_normal; | |
15809 } | |
15810 if (background->type == NK_STYLE_ITEM_IMAGE) | |
15811 background_color = nk_rgba(0,0,0,0); | |
15812 else background_color = background->data.color; | |
15813 | |
15814 | |
15815 if (edit->select_start == edit->select_end) { | |
15816 /* no selection so just draw the complete text */ | |
15817 const char *begin = nk_str_get_const(&edit->string); | |
15818 int l = nk_str_len_char(&edit->string); | |
15819 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, | |
15820 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, | |
15821 background_color, text_color, nk_false); | |
15822 } else { | |
15823 /* edit has selection so draw 1-3 text chunks */ | |
15824 if (edit->select_start != edit->select_end && selection_begin > 0){ | |
15825 /* draw unselected text before selection */ | |
15826 const char *begin = nk_str_get_const(&edit->string); | |
15827 NK_ASSERT(select_begin_ptr); | |
15828 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, | |
15829 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), | |
15830 row_height, font, background_color, text_color, nk_false); | |
15831 } | |
15832 if (edit->select_start != edit->select_end) { | |
15833 /* draw selected text */ | |
15834 NK_ASSERT(select_begin_ptr); | |
15835 if (!select_end_ptr) { | |
15836 const char *begin = nk_str_get_const(&edit->string); | |
15837 select_end_ptr = begin + nk_str_len_char(&edit->string); | |
15838 } | |
15839 nk_edit_draw_text(out, style, | |
15840 area.x - edit->scrollbar.x, | |
15841 area.y + selection_offset_start.y - edit->scrollbar.y, | |
15842 selection_offset_start.x, | |
15843 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), | |
15844 row_height, font, sel_background_color, sel_text_color, nk_true); | |
15845 } | |
15846 if ((edit->select_start != edit->select_end && | |
15847 selection_end < edit->string.len)) | |
15848 { | |
15849 /* draw unselected text after selected text */ | |
15850 const char *begin = select_end_ptr; | |
15851 const char *end = nk_str_get_const(&edit->string) + | |
15852 nk_str_len_char(&edit->string); | |
15853 NK_ASSERT(select_end_ptr); | |
15854 nk_edit_draw_text(out, style, | |
15855 area.x - edit->scrollbar.x, | |
15856 area.y + selection_offset_end.y - edit->scrollbar.y, | |
15857 selection_offset_end.x, | |
15858 begin, (int)(end - begin), row_height, font, | |
15859 background_color, text_color, nk_true); | |
15860 } | |
15861 } | |
15862 | |
15863 /* cursor */ | |
15864 if (edit->select_start == edit->select_end) | |
15865 { | |
15866 if (edit->cursor >= nk_str_len(&edit->string) || | |
15867 (cursor_ptr && *cursor_ptr == '\n')) { | |
15868 /* draw cursor at end of line */ | |
15869 struct nk_rect cursor; | |
15870 cursor.w = style->cursor_size; | |
15871 cursor.h = font->height; | |
15872 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; | |
15873 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; | |
15874 cursor.y -= edit->scrollbar.y; | |
15875 nk_fill_rect(out, cursor, 0, cursor_color); | |
15876 } else { | |
15877 /* draw cursor inside text */ | |
15878 int glyph_len; | |
15879 struct nk_rect label; | |
15880 struct nk_text txt; | |
15881 | |
15882 nk_rune unicode; | |
15883 NK_ASSERT(cursor_ptr); | |
15884 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); | |
15885 | |
15886 label.x = area.x + cursor_pos.x - edit->scrollbar.x; | |
15887 label.y = area.y + cursor_pos.y - edit->scrollbar.y; | |
15888 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); | |
15889 label.h = row_height; | |
15890 | |
15891 txt.padding = nk_vec2(0,0); | |
15892 txt.background = cursor_color;; | |
15893 txt.text = cursor_text_color; | |
15894 nk_fill_rect(out, label, 0, cursor_color); | |
15895 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); | |
15896 } | |
15897 }} | |
15898 } else { | |
15899 /* not active so just draw text */ | |
15900 int l = nk_str_len_char(&edit->string); | |
15901 const char *begin = nk_str_get_const(&edit->string); | |
15902 | |
15903 const struct nk_style_item *background; | |
15904 struct nk_color background_color; | |
15905 struct nk_color text_color; | |
15906 nk_push_scissor(out, clip); | |
15907 if (*state & NK_WIDGET_STATE_ACTIVED) { | |
15908 background = &style->active; | |
15909 text_color = style->text_active; | |
15910 } else if (*state & NK_WIDGET_STATE_HOVER) { | |
15911 background = &style->hover; | |
15912 text_color = style->text_hover; | |
15913 } else { | |
15914 background = &style->normal; | |
15915 text_color = style->text_normal; | |
15916 } | |
15917 if (background->type == NK_STYLE_ITEM_IMAGE) | |
15918 background_color = nk_rgba(0,0,0,0); | |
15919 else background_color = background->data.color; | |
15920 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, | |
15921 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, | |
15922 background_color, text_color, nk_false); | |
15923 } | |
15924 nk_push_scissor(out, old_clip);} | |
15925 return ret; | |
15926 } | |
15927 | |
15928 /* =============================================================== | |
15929 * | |
15930 * PROPERTY | |
15931 * | |
15932 * ===============================================================*/ | |
15933 enum nk_property_status { | |
15934 NK_PROPERTY_DEFAULT, | |
15935 NK_PROPERTY_EDIT, | |
15936 NK_PROPERTY_DRAG | |
15937 }; | |
15938 enum nk_property_filter { | |
15939 NK_FILTER_INT, | |
15940 NK_FILTER_FLOAT | |
15941 }; | |
15942 enum nk_property_kind { | |
15943 NK_PROPERTY_INT, | |
15944 NK_PROPERTY_FLOAT, | |
15945 NK_PROPERTY_DOUBLE | |
15946 }; | |
15947 union nk_property { | |
15948 int i; | |
15949 float f; | |
15950 double d; | |
15951 }; | |
15952 struct nk_property_variant { | |
15953 enum nk_property_kind kind; | |
15954 union nk_property value; | |
15955 union nk_property min_value; | |
15956 union nk_property max_value; | |
15957 union nk_property step; | |
15958 }; | |
15959 | |
15960 NK_INTERN void | |
15961 nk_drag_behavior(nk_flags *state, const struct nk_input *in, | |
15962 struct nk_rect drag, struct nk_property_variant *variant, | |
15963 float inc_per_pixel) | |
15964 { | |
15965 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; | |
15966 int left_mouse_click_in_cursor = in && | |
15967 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); | |
15968 | |
15969 nk_widget_state_reset(state); | |
15970 if (nk_input_is_mouse_hovering_rect(in, drag)) | |
15971 *state = NK_WIDGET_STATE_HOVERED; | |
15972 | |
15973 if (left_mouse_down && left_mouse_click_in_cursor) { | |
15974 float delta, pixels; | |
15975 pixels = in->mouse.delta.x; | |
15976 delta = pixels * inc_per_pixel; | |
15977 switch (variant->kind) { | |
15978 default: break; | |
15979 case NK_PROPERTY_INT: | |
15980 variant->value.i = variant->value.i + (int)delta; | |
15981 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); | |
15982 break; | |
15983 case NK_PROPERTY_FLOAT: | |
15984 variant->value.f = variant->value.f + (float)delta; | |
15985 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); | |
15986 break; | |
15987 case NK_PROPERTY_DOUBLE: | |
15988 variant->value.d = variant->value.d + (double)delta; | |
15989 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); | |
15990 break; | |
15991 } | |
15992 *state = NK_WIDGET_STATE_ACTIVE; | |
15993 } | |
15994 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) | |
15995 *state |= NK_WIDGET_STATE_ENTERED; | |
15996 else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) | |
15997 *state |= NK_WIDGET_STATE_LEFT; | |
15998 } | |
15999 | |
16000 NK_INTERN void | |
16001 nk_property_behavior(nk_flags *ws, const struct nk_input *in, | |
16002 struct nk_rect property, struct nk_rect label, struct nk_rect edit, | |
16003 struct nk_rect empty, int *state, struct nk_property_variant *variant, | |
16004 float inc_per_pixel) | |
16005 { | |
16006 if (in && *state == NK_PROPERTY_DEFAULT) { | |
16007 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) | |
16008 *state = NK_PROPERTY_EDIT; | |
16009 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) | |
16010 *state = NK_PROPERTY_DRAG; | |
16011 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) | |
16012 *state = NK_PROPERTY_DRAG; | |
16013 } | |
16014 if (*state == NK_PROPERTY_DRAG) { | |
16015 nk_drag_behavior(ws, in, property, variant, inc_per_pixel); | |
16016 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; | |
16017 } | |
16018 } | |
16019 | |
16020 NK_INTERN void | |
16021 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, | |
16022 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, | |
16023 const char *name, int len, const struct nk_user_font *font) | |
16024 { | |
16025 struct nk_text text; | |
16026 const struct nk_style_item *background; | |
16027 | |
16028 /* select correct background and text color */ | |
16029 if (state & NK_WIDGET_STATE_ACTIVED) { | |
16030 background = &style->active; | |
16031 text.text = style->label_active; | |
16032 } else if (state & NK_WIDGET_STATE_HOVER) { | |
16033 background = &style->hover; | |
16034 text.text = style->label_hover; | |
16035 } else { | |
16036 background = &style->normal; | |
16037 text.text = style->label_normal; | |
16038 } | |
16039 | |
16040 /* draw background */ | |
16041 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
16042 nk_draw_image(out, *bounds, &background->data.image, nk_white); | |
16043 text.background = nk_rgba(0,0,0,0); | |
16044 } else { | |
16045 text.background = background->data.color; | |
16046 nk_fill_rect(out, *bounds, style->rounding, background->data.color); | |
16047 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); | |
16048 } | |
16049 | |
16050 /* draw label */ | |
16051 text.padding = nk_vec2(0,0); | |
16052 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); | |
16053 } | |
16054 | |
16055 NK_INTERN void | |
16056 nk_do_property(nk_flags *ws, | |
16057 struct nk_command_buffer *out, struct nk_rect property, | |
16058 const char *name, struct nk_property_variant *variant, | |
16059 float inc_per_pixel, char *buffer, int *len, | |
16060 int *state, int *cursor, int *select_begin, int *select_end, | |
16061 const struct nk_style_property *style, | |
16062 enum nk_property_filter filter, struct nk_input *in, | |
16063 const struct nk_user_font *font, struct nk_text_edit *text_edit, | |
16064 enum nk_button_behavior behavior) | |
16065 { | |
16066 const nk_plugin_filter filters[] = { | |
16067 nk_filter_decimal, | |
16068 nk_filter_float | |
16069 }; | |
16070 int active, old; | |
16071 int num_len, name_len; | |
16072 char string[NK_MAX_NUMBER_BUFFER]; | |
16073 float size; | |
16074 | |
16075 char *dst = 0; | |
16076 int *length; | |
16077 | |
16078 struct nk_rect left; | |
16079 struct nk_rect right; | |
16080 struct nk_rect label; | |
16081 struct nk_rect edit; | |
16082 struct nk_rect empty; | |
16083 | |
16084 /* left decrement button */ | |
16085 left.h = font->height/2; | |
16086 left.w = left.h; | |
16087 left.x = property.x + style->border + style->padding.x; | |
16088 left.y = property.y + style->border + property.h/2.0f - left.h/2; | |
16089 | |
16090 /* text label */ | |
16091 name_len = nk_strlen(name); | |
16092 size = font->width(font->userdata, font->height, name, name_len); | |
16093 label.x = left.x + left.w + style->padding.x; | |
16094 label.w = (float)size + 2 * style->padding.x; | |
16095 label.y = property.y + style->border + style->padding.y; | |
16096 label.h = property.h - (2 * style->border + 2 * style->padding.y); | |
16097 | |
16098 /* right increment button */ | |
16099 right.y = left.y; | |
16100 right.w = left.w; | |
16101 right.h = left.h; | |
16102 right.x = property.x + property.w - (right.w + style->padding.x); | |
16103 | |
16104 /* edit */ | |
16105 if (*state == NK_PROPERTY_EDIT) { | |
16106 size = font->width(font->userdata, font->height, buffer, *len); | |
16107 size += style->edit.cursor_size; | |
16108 length = len; | |
16109 dst = buffer; | |
16110 } else { | |
16111 switch (variant->kind) { | |
16112 default: break; | |
16113 case NK_PROPERTY_INT: | |
16114 nk_itoa(string, variant->value.i); | |
16115 num_len = nk_strlen(string); | |
16116 break; | |
16117 case NK_PROPERTY_FLOAT: | |
16118 nk_dtoa(string, (double)variant->value.f); | |
16119 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); | |
16120 break; | |
16121 case NK_PROPERTY_DOUBLE: | |
16122 nk_dtoa(string, variant->value.d); | |
16123 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); | |
16124 break; | |
16125 } | |
16126 size = font->width(font->userdata, font->height, string, num_len); | |
16127 dst = string; | |
16128 length = &num_len; | |
16129 } | |
16130 | |
16131 edit.w = (float)size + 2 * style->padding.x; | |
16132 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); | |
16133 edit.x = right.x - (edit.w + style->padding.x); | |
16134 edit.y = property.y + style->border; | |
16135 edit.h = property.h - (2 * style->border); | |
16136 | |
16137 /* empty left space activator */ | |
16138 empty.w = edit.x - (label.x + label.w); | |
16139 empty.x = label.x + label.w; | |
16140 empty.y = property.y; | |
16141 empty.h = property.h; | |
16142 | |
16143 /* update property */ | |
16144 old = (*state == NK_PROPERTY_EDIT); | |
16145 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); | |
16146 | |
16147 /* draw property */ | |
16148 if (style->draw_begin) style->draw_begin(out, style->userdata); | |
16149 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); | |
16150 if (style->draw_end) style->draw_end(out, style->userdata); | |
16151 | |
16152 /* execute right button */ | |
16153 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) { | |
16154 switch (variant->kind) { | |
16155 default: break; | |
16156 case NK_PROPERTY_INT: | |
16157 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; | |
16158 case NK_PROPERTY_FLOAT: | |
16159 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; | |
16160 case NK_PROPERTY_DOUBLE: | |
16161 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; | |
16162 } | |
16163 } | |
16164 /* execute left button */ | |
16165 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) { | |
16166 switch (variant->kind) { | |
16167 default: break; | |
16168 case NK_PROPERTY_INT: | |
16169 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; | |
16170 case NK_PROPERTY_FLOAT: | |
16171 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; | |
16172 case NK_PROPERTY_DOUBLE: | |
16173 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; | |
16174 } | |
16175 } | |
16176 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) { | |
16177 /* property has been activated so setup buffer */ | |
16178 NK_MEMCPY(buffer, dst, (nk_size)*length); | |
16179 *cursor = nk_utf_len(buffer, *length); | |
16180 *len = *length; | |
16181 length = len; | |
16182 dst = buffer; | |
16183 active = 0; | |
16184 } else active = (*state == NK_PROPERTY_EDIT); | |
16185 | |
16186 /* execute and run text edit field */ | |
16187 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); | |
16188 text_edit->active = (unsigned char)active; | |
16189 text_edit->string.len = *length; | |
16190 text_edit->cursor = NK_CLAMP(0, *cursor, *length); | |
16191 text_edit->select_start = NK_CLAMP(0,*select_begin, *length); | |
16192 text_edit->select_end = NK_CLAMP(0,*select_end, *length); | |
16193 text_edit->string.buffer.allocated = (nk_size)*length; | |
16194 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; | |
16195 text_edit->string.buffer.memory.ptr = dst; | |
16196 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; | |
16197 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; | |
16198 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT, | |
16199 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); | |
16200 | |
16201 *length = text_edit->string.len; | |
16202 *cursor = text_edit->cursor; | |
16203 *select_begin = text_edit->select_start; | |
16204 *select_end = text_edit->select_end; | |
16205 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) | |
16206 text_edit->active = nk_false; | |
16207 | |
16208 if (active && !text_edit->active) { | |
16209 /* property is now not active so convert edit text to value*/ | |
16210 *state = NK_PROPERTY_DEFAULT; | |
16211 buffer[*len] = '\0'; | |
16212 switch (variant->kind) { | |
16213 default: break; | |
16214 case NK_PROPERTY_INT: | |
16215 variant->value.i = nk_strtoi(buffer, 0); | |
16216 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); | |
16217 break; | |
16218 case NK_PROPERTY_FLOAT: | |
16219 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); | |
16220 variant->value.f = nk_strtof(buffer, 0); | |
16221 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); | |
16222 break; | |
16223 case NK_PROPERTY_DOUBLE: | |
16224 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); | |
16225 variant->value.d = nk_strtod(buffer, 0); | |
16226 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); | |
16227 break; | |
16228 } | |
16229 } | |
16230 } | |
16231 /* =============================================================== | |
16232 * | |
16233 * COLOR PICKER | |
16234 * | |
16235 * ===============================================================*/ | |
16236 NK_INTERN int | |
16237 nk_color_picker_behavior(nk_flags *state, | |
16238 const struct nk_rect *bounds, const struct nk_rect *matrix, | |
16239 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, | |
16240 struct nk_color *color, const struct nk_input *in) | |
16241 { | |
16242 float hsva[4]; | |
16243 int value_changed = 0; | |
16244 int hsv_changed = 0; | |
16245 | |
16246 NK_ASSERT(state); | |
16247 NK_ASSERT(matrix); | |
16248 NK_ASSERT(hue_bar); | |
16249 NK_ASSERT(color); | |
16250 | |
16251 /* color matrix */ | |
16252 nk_color_hsva_fv(hsva, *color); | |
16253 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { | |
16254 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); | |
16255 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); | |
16256 value_changed = hsv_changed = 1; | |
16257 } | |
16258 | |
16259 /* hue bar */ | |
16260 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { | |
16261 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); | |
16262 value_changed = hsv_changed = 1; | |
16263 } | |
16264 | |
16265 /* alpha bar */ | |
16266 if (alpha_bar) { | |
16267 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { | |
16268 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); | |
16269 value_changed = 1; | |
16270 } | |
16271 } | |
16272 nk_widget_state_reset(state); | |
16273 if (hsv_changed) { | |
16274 *color = nk_hsva_fv(hsva); | |
16275 *state = NK_WIDGET_STATE_ACTIVE; | |
16276 } | |
16277 if (value_changed) { | |
16278 color->a = (nk_byte)(hsva[3] * 255.0f); | |
16279 *state = NK_WIDGET_STATE_ACTIVE; | |
16280 } | |
16281 | |
16282 /* set color picker widget state */ | |
16283 if (nk_input_is_mouse_hovering_rect(in, *bounds)) | |
16284 *state = NK_WIDGET_STATE_HOVERED; | |
16285 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) | |
16286 *state |= NK_WIDGET_STATE_ENTERED; | |
16287 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) | |
16288 *state |= NK_WIDGET_STATE_LEFT; | |
16289 return value_changed; | |
16290 } | |
16291 | |
16292 NK_INTERN void | |
16293 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, | |
16294 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, | |
16295 struct nk_color color) | |
16296 { | |
16297 NK_STORAGE const struct nk_color black = {0,0,0,255}; | |
16298 NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; | |
16299 NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; | |
16300 | |
16301 const float crosshair_size = 7.0f; | |
16302 struct nk_color temp; | |
16303 float hsva[4]; | |
16304 float line_y; | |
16305 int i; | |
16306 | |
16307 NK_ASSERT(o); | |
16308 NK_ASSERT(matrix); | |
16309 NK_ASSERT(hue_bar); | |
16310 | |
16311 /* draw hue bar */ | |
16312 nk_color_hsv_fv(hsva, color); | |
16313 for (i = 0; i < 6; ++i) { | |
16314 NK_GLOBAL const struct nk_color hue_colors[] = { | |
16315 {255, 0, 0, 255}, | |
16316 {255,255,0,255}, | |
16317 {0,255,0,255}, | |
16318 {0, 255,255,255}, | |
16319 {0,0,255,255}, | |
16320 {255, 0, 255, 255}, | |
16321 {255, 0, 0, 255} | |
16322 }; | |
16323 nk_fill_rect_multi_color(o, | |
16324 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, | |
16325 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], | |
16326 hue_colors[i+1], hue_colors[i+1]); | |
16327 } | |
16328 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); | |
16329 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, | |
16330 line_y, 1, nk_rgb(255,255,255)); | |
16331 | |
16332 /* draw alpha bar */ | |
16333 if (alpha_bar) { | |
16334 float alpha = NK_SATURATE((float)color.a/255.0f); | |
16335 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); | |
16336 | |
16337 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); | |
16338 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, | |
16339 line_y, 1, nk_rgb(255,255,255)); | |
16340 } | |
16341 | |
16342 /* draw color matrix */ | |
16343 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); | |
16344 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); | |
16345 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); | |
16346 | |
16347 /* draw cross-hair */ | |
16348 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; | |
16349 p.x = (float)(int)(matrix->x + S * matrix->w); | |
16350 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); | |
16351 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); | |
16352 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); | |
16353 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); | |
16354 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} | |
16355 } | |
16356 | |
16357 NK_INTERN int | |
16358 nk_do_color_picker(nk_flags *state, | |
16359 struct nk_command_buffer *out, struct nk_color *color, | |
16360 enum nk_color_format fmt, struct nk_rect bounds, | |
16361 struct nk_vec2 padding, const struct nk_input *in, | |
16362 const struct nk_user_font *font) | |
16363 { | |
16364 int ret = 0; | |
16365 struct nk_rect matrix; | |
16366 struct nk_rect hue_bar; | |
16367 struct nk_rect alpha_bar; | |
16368 float bar_w; | |
16369 | |
16370 NK_ASSERT(out); | |
16371 NK_ASSERT(color); | |
16372 NK_ASSERT(state); | |
16373 NK_ASSERT(font); | |
16374 if (!out || !color || !state || !font) | |
16375 return ret; | |
16376 | |
16377 bar_w = font->height; | |
16378 bounds.x += padding.x; | |
16379 bounds.y += padding.x; | |
16380 bounds.w -= 2 * padding.x; | |
16381 bounds.h -= 2 * padding.y; | |
16382 | |
16383 matrix.x = bounds.x; | |
16384 matrix.y = bounds.y; | |
16385 matrix.h = bounds.h; | |
16386 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); | |
16387 | |
16388 hue_bar.w = bar_w; | |
16389 hue_bar.y = bounds.y; | |
16390 hue_bar.h = matrix.h; | |
16391 hue_bar.x = matrix.x + matrix.w + padding.x; | |
16392 | |
16393 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; | |
16394 alpha_bar.y = bounds.y; | |
16395 alpha_bar.w = bar_w; | |
16396 alpha_bar.h = matrix.h; | |
16397 | |
16398 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, | |
16399 (fmt == NK_RGBA) ? &alpha_bar:0, color, in); | |
16400 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color); | |
16401 return ret; | |
16402 } | |
16403 | |
16404 /* ============================================================== | |
16405 * | |
16406 * STYLE | |
16407 * | |
16408 * ===============================================================*/ | |
16409 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} | |
16410 #define NK_COLOR_MAP(NK_COLOR)\ | |
16411 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ | |
16412 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ | |
16413 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ | |
16414 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ | |
16415 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ | |
16416 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ | |
16417 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ | |
16418 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ | |
16419 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ | |
16420 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ | |
16421 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ | |
16422 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ | |
16423 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ | |
16424 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ | |
16425 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ | |
16426 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ | |
16427 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ | |
16428 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ | |
16429 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ | |
16430 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ | |
16431 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ | |
16432 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ | |
16433 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \ | |
16434 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ | |
16435 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ | |
16436 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \ | |
16437 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \ | |
16438 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) | |
16439 | |
16440 NK_GLOBAL const struct nk_color | |
16441 nk_default_color_style[NK_COLOR_COUNT] = { | |
16442 #define NK_COLOR(a,b,c,d,e) {b,c,d,e}, | |
16443 NK_COLOR_MAP(NK_COLOR) | |
16444 #undef NK_COLOR | |
16445 }; | |
16446 | |
16447 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { | |
16448 #define NK_COLOR(a,b,c,d,e) #a, | |
16449 NK_COLOR_MAP(NK_COLOR) | |
16450 #undef NK_COLOR | |
16451 }; | |
16452 | |
16453 NK_API const char *nk_style_get_color_by_name(enum nk_style_colors c) | |
16454 {return nk_color_names[c];} | |
16455 | |
16456 NK_API struct nk_style_item nk_style_item_image(struct nk_image img) | |
16457 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;} | |
16458 | |
16459 NK_API struct nk_style_item nk_style_item_color(struct nk_color col) | |
16460 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;} | |
16461 | |
16462 NK_API struct nk_style_item nk_style_item_hide(void) | |
16463 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;} | |
16464 | |
16465 NK_API void | |
16466 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) | |
16467 { | |
16468 struct nk_style *style; | |
16469 struct nk_style_text *text; | |
16470 struct nk_style_button *button; | |
16471 struct nk_style_toggle *toggle; | |
16472 struct nk_style_selectable *select; | |
16473 struct nk_style_slider *slider; | |
16474 struct nk_style_progress *prog; | |
16475 struct nk_style_scrollbar *scroll; | |
16476 struct nk_style_edit *edit; | |
16477 struct nk_style_property *property; | |
16478 struct nk_style_combo *combo; | |
16479 struct nk_style_chart *chart; | |
16480 struct nk_style_tab *tab; | |
16481 struct nk_style_window *win; | |
16482 | |
16483 NK_ASSERT(ctx); | |
16484 if (!ctx) return; | |
16485 style = &ctx->style; | |
16486 table = (!table) ? nk_default_color_style: table; | |
16487 | |
16488 /* default text */ | |
16489 text = &style->text; | |
16490 text->color = table[NK_COLOR_TEXT]; | |
16491 text->padding = nk_vec2(0,0); | |
16492 | |
16493 /* default button */ | |
16494 button = &style->button; | |
16495 nk_zero_struct(*button); | |
16496 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); | |
16497 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); | |
16498 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); | |
16499 button->border_color = table[NK_COLOR_BORDER]; | |
16500 button->text_background = table[NK_COLOR_BUTTON]; | |
16501 button->text_normal = table[NK_COLOR_TEXT]; | |
16502 button->text_hover = table[NK_COLOR_TEXT]; | |
16503 button->text_active = table[NK_COLOR_TEXT]; | |
16504 button->padding = nk_vec2(2.0f,2.0f); | |
16505 button->image_padding = nk_vec2(0.0f,0.0f); | |
16506 button->touch_padding = nk_vec2(0.0f, 0.0f); | |
16507 button->userdata = nk_handle_ptr(0); | |
16508 button->text_alignment = NK_TEXT_CENTERED; | |
16509 button->border = 1.0f; | |
16510 button->rounding = 4.0f; | |
16511 button->draw_begin = 0; | |
16512 button->draw_end = 0; | |
16513 | |
16514 /* contextual button */ | |
16515 button = &style->contextual_button; | |
16516 nk_zero_struct(*button); | |
16517 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16518 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); | |
16519 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); | |
16520 button->border_color = table[NK_COLOR_WINDOW]; | |
16521 button->text_background = table[NK_COLOR_WINDOW]; | |
16522 button->text_normal = table[NK_COLOR_TEXT]; | |
16523 button->text_hover = table[NK_COLOR_TEXT]; | |
16524 button->text_active = table[NK_COLOR_TEXT]; | |
16525 button->padding = nk_vec2(2.0f,2.0f); | |
16526 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16527 button->userdata = nk_handle_ptr(0); | |
16528 button->text_alignment = NK_TEXT_CENTERED; | |
16529 button->border = 0.0f; | |
16530 button->rounding = 0.0f; | |
16531 button->draw_begin = 0; | |
16532 button->draw_end = 0; | |
16533 | |
16534 /* menu button */ | |
16535 button = &style->menu_button; | |
16536 nk_zero_struct(*button); | |
16537 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16538 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16539 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16540 button->border_color = table[NK_COLOR_WINDOW]; | |
16541 button->text_background = table[NK_COLOR_WINDOW]; | |
16542 button->text_normal = table[NK_COLOR_TEXT]; | |
16543 button->text_hover = table[NK_COLOR_TEXT]; | |
16544 button->text_active = table[NK_COLOR_TEXT]; | |
16545 button->padding = nk_vec2(2.0f,2.0f); | |
16546 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16547 button->userdata = nk_handle_ptr(0); | |
16548 button->text_alignment = NK_TEXT_CENTERED; | |
16549 button->border = 0.0f; | |
16550 button->rounding = 1.0f; | |
16551 button->draw_begin = 0; | |
16552 button->draw_end = 0; | |
16553 | |
16554 /* checkbox toggle */ | |
16555 toggle = &style->checkbox; | |
16556 nk_zero_struct(*toggle); | |
16557 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); | |
16558 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); | |
16559 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); | |
16560 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); | |
16561 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); | |
16562 toggle->userdata = nk_handle_ptr(0); | |
16563 toggle->text_background = table[NK_COLOR_WINDOW]; | |
16564 toggle->text_normal = table[NK_COLOR_TEXT]; | |
16565 toggle->text_hover = table[NK_COLOR_TEXT]; | |
16566 toggle->text_active = table[NK_COLOR_TEXT]; | |
16567 toggle->padding = nk_vec2(2.0f, 2.0f); | |
16568 toggle->touch_padding = nk_vec2(0,0); | |
16569 toggle->border_color = nk_rgba(0,0,0,0); | |
16570 toggle->border = 0.0f; | |
16571 toggle->spacing = 4; | |
16572 | |
16573 /* option toggle */ | |
16574 toggle = &style->option; | |
16575 nk_zero_struct(*toggle); | |
16576 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); | |
16577 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); | |
16578 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); | |
16579 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); | |
16580 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); | |
16581 toggle->userdata = nk_handle_ptr(0); | |
16582 toggle->text_background = table[NK_COLOR_WINDOW]; | |
16583 toggle->text_normal = table[NK_COLOR_TEXT]; | |
16584 toggle->text_hover = table[NK_COLOR_TEXT]; | |
16585 toggle->text_active = table[NK_COLOR_TEXT]; | |
16586 toggle->padding = nk_vec2(3.0f, 3.0f); | |
16587 toggle->touch_padding = nk_vec2(0,0); | |
16588 toggle->border_color = nk_rgba(0,0,0,0); | |
16589 toggle->border = 0.0f; | |
16590 toggle->spacing = 4; | |
16591 | |
16592 /* selectable */ | |
16593 select = &style->selectable; | |
16594 nk_zero_struct(*select); | |
16595 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); | |
16596 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); | |
16597 select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); | |
16598 select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); | |
16599 select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); | |
16600 select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); | |
16601 select->text_normal = table[NK_COLOR_TEXT]; | |
16602 select->text_hover = table[NK_COLOR_TEXT]; | |
16603 select->text_pressed = table[NK_COLOR_TEXT]; | |
16604 select->text_normal_active = table[NK_COLOR_TEXT]; | |
16605 select->text_hover_active = table[NK_COLOR_TEXT]; | |
16606 select->text_pressed_active = table[NK_COLOR_TEXT]; | |
16607 select->padding = nk_vec2(2.0f,2.0f); | |
16608 select->touch_padding = nk_vec2(0,0); | |
16609 select->userdata = nk_handle_ptr(0); | |
16610 select->rounding = 0.0f; | |
16611 select->draw_begin = 0; | |
16612 select->draw_end = 0; | |
16613 | |
16614 /* slider */ | |
16615 slider = &style->slider; | |
16616 nk_zero_struct(*slider); | |
16617 slider->normal = nk_style_item_hide(); | |
16618 slider->hover = nk_style_item_hide(); | |
16619 slider->active = nk_style_item_hide(); | |
16620 slider->bar_normal = table[NK_COLOR_SLIDER]; | |
16621 slider->bar_hover = table[NK_COLOR_SLIDER]; | |
16622 slider->bar_active = table[NK_COLOR_SLIDER]; | |
16623 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; | |
16624 slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); | |
16625 slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); | |
16626 slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); | |
16627 slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; | |
16628 slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; | |
16629 slider->cursor_size = nk_vec2(16,16); | |
16630 slider->padding = nk_vec2(2,2); | |
16631 slider->spacing = nk_vec2(2,2); | |
16632 slider->userdata = nk_handle_ptr(0); | |
16633 slider->show_buttons = nk_false; | |
16634 slider->bar_height = 8; | |
16635 slider->rounding = 0; | |
16636 slider->draw_begin = 0; | |
16637 slider->draw_end = 0; | |
16638 | |
16639 /* slider buttons */ | |
16640 button = &style->slider.inc_button; | |
16641 button->normal = nk_style_item_color(nk_rgb(40,40,40)); | |
16642 button->hover = nk_style_item_color(nk_rgb(42,42,42)); | |
16643 button->active = nk_style_item_color(nk_rgb(44,44,44)); | |
16644 button->border_color = nk_rgb(65,65,65); | |
16645 button->text_background = nk_rgb(40,40,40); | |
16646 button->text_normal = nk_rgb(175,175,175); | |
16647 button->text_hover = nk_rgb(175,175,175); | |
16648 button->text_active = nk_rgb(175,175,175); | |
16649 button->padding = nk_vec2(8.0f,8.0f); | |
16650 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16651 button->userdata = nk_handle_ptr(0); | |
16652 button->text_alignment = NK_TEXT_CENTERED; | |
16653 button->border = 1.0f; | |
16654 button->rounding = 0.0f; | |
16655 button->draw_begin = 0; | |
16656 button->draw_end = 0; | |
16657 style->slider.dec_button = style->slider.inc_button; | |
16658 | |
16659 /* progressbar */ | |
16660 prog = &style->progress; | |
16661 nk_zero_struct(*prog); | |
16662 prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); | |
16663 prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); | |
16664 prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); | |
16665 prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); | |
16666 prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); | |
16667 prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); | |
16668 prog->border_color = nk_rgba(0,0,0,0); | |
16669 prog->cursor_border_color = nk_rgba(0,0,0,0); | |
16670 prog->userdata = nk_handle_ptr(0); | |
16671 prog->padding = nk_vec2(4,4); | |
16672 prog->rounding = 0; | |
16673 prog->border = 0; | |
16674 prog->cursor_rounding = 0; | |
16675 prog->cursor_border = 0; | |
16676 prog->draw_begin = 0; | |
16677 prog->draw_end = 0; | |
16678 | |
16679 /* scrollbars */ | |
16680 scroll = &style->scrollh; | |
16681 nk_zero_struct(*scroll); | |
16682 scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); | |
16683 scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); | |
16684 scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); | |
16685 scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); | |
16686 scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); | |
16687 scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); | |
16688 scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; | |
16689 scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; | |
16690 scroll->userdata = nk_handle_ptr(0); | |
16691 scroll->border_color = table[NK_COLOR_SCROLLBAR]; | |
16692 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; | |
16693 scroll->padding = nk_vec2(0,0); | |
16694 scroll->show_buttons = nk_false; | |
16695 scroll->border = 0; | |
16696 scroll->rounding = 0; | |
16697 scroll->border_cursor = 0; | |
16698 scroll->rounding_cursor = 0; | |
16699 scroll->draw_begin = 0; | |
16700 scroll->draw_end = 0; | |
16701 style->scrollv = style->scrollh; | |
16702 | |
16703 /* scrollbars buttons */ | |
16704 button = &style->scrollh.inc_button; | |
16705 button->normal = nk_style_item_color(nk_rgb(40,40,40)); | |
16706 button->hover = nk_style_item_color(nk_rgb(42,42,42)); | |
16707 button->active = nk_style_item_color(nk_rgb(44,44,44)); | |
16708 button->border_color = nk_rgb(65,65,65); | |
16709 button->text_background = nk_rgb(40,40,40); | |
16710 button->text_normal = nk_rgb(175,175,175); | |
16711 button->text_hover = nk_rgb(175,175,175); | |
16712 button->text_active = nk_rgb(175,175,175); | |
16713 button->padding = nk_vec2(4.0f,4.0f); | |
16714 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16715 button->userdata = nk_handle_ptr(0); | |
16716 button->text_alignment = NK_TEXT_CENTERED; | |
16717 button->border = 1.0f; | |
16718 button->rounding = 0.0f; | |
16719 button->draw_begin = 0; | |
16720 button->draw_end = 0; | |
16721 style->scrollh.dec_button = style->scrollh.inc_button; | |
16722 style->scrollv.inc_button = style->scrollh.inc_button; | |
16723 style->scrollv.dec_button = style->scrollh.inc_button; | |
16724 | |
16725 /* edit */ | |
16726 edit = &style->edit; | |
16727 nk_zero_struct(*edit); | |
16728 edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); | |
16729 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); | |
16730 edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); | |
16731 edit->cursor_normal = table[NK_COLOR_TEXT]; | |
16732 edit->cursor_hover = table[NK_COLOR_TEXT]; | |
16733 edit->cursor_text_normal= table[NK_COLOR_EDIT]; | |
16734 edit->cursor_text_hover = table[NK_COLOR_EDIT]; | |
16735 edit->border_color = table[NK_COLOR_BORDER]; | |
16736 edit->text_normal = table[NK_COLOR_TEXT]; | |
16737 edit->text_hover = table[NK_COLOR_TEXT]; | |
16738 edit->text_active = table[NK_COLOR_TEXT]; | |
16739 edit->selected_normal = table[NK_COLOR_TEXT]; | |
16740 edit->selected_hover = table[NK_COLOR_TEXT]; | |
16741 edit->selected_text_normal = table[NK_COLOR_EDIT]; | |
16742 edit->selected_text_hover = table[NK_COLOR_EDIT]; | |
16743 edit->scrollbar_size = nk_vec2(10,10); | |
16744 edit->scrollbar = style->scrollv; | |
16745 edit->padding = nk_vec2(4,4); | |
16746 edit->row_padding = 2; | |
16747 edit->cursor_size = 4; | |
16748 edit->border = 1; | |
16749 edit->rounding = 0; | |
16750 | |
16751 /* property */ | |
16752 property = &style->property; | |
16753 nk_zero_struct(*property); | |
16754 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16755 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16756 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16757 property->border_color = table[NK_COLOR_BORDER]; | |
16758 property->label_normal = table[NK_COLOR_TEXT]; | |
16759 property->label_hover = table[NK_COLOR_TEXT]; | |
16760 property->label_active = table[NK_COLOR_TEXT]; | |
16761 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; | |
16762 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; | |
16763 property->userdata = nk_handle_ptr(0); | |
16764 property->padding = nk_vec2(4,4); | |
16765 property->border = 1; | |
16766 property->rounding = 10; | |
16767 property->draw_begin = 0; | |
16768 property->draw_end = 0; | |
16769 | |
16770 /* property buttons */ | |
16771 button = &style->property.dec_button; | |
16772 nk_zero_struct(*button); | |
16773 button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16774 button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16775 button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16776 button->border_color = nk_rgba(0,0,0,0); | |
16777 button->text_background = table[NK_COLOR_PROPERTY]; | |
16778 button->text_normal = table[NK_COLOR_TEXT]; | |
16779 button->text_hover = table[NK_COLOR_TEXT]; | |
16780 button->text_active = table[NK_COLOR_TEXT]; | |
16781 button->padding = nk_vec2(0.0f,0.0f); | |
16782 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16783 button->userdata = nk_handle_ptr(0); | |
16784 button->text_alignment = NK_TEXT_CENTERED; | |
16785 button->border = 0.0f; | |
16786 button->rounding = 0.0f; | |
16787 button->draw_begin = 0; | |
16788 button->draw_end = 0; | |
16789 style->property.inc_button = style->property.dec_button; | |
16790 | |
16791 /* property edit */ | |
16792 edit = &style->property.edit; | |
16793 nk_zero_struct(*edit); | |
16794 edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16795 edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16796 edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); | |
16797 edit->border_color = nk_rgba(0,0,0,0); | |
16798 edit->cursor_normal = table[NK_COLOR_TEXT]; | |
16799 edit->cursor_hover = table[NK_COLOR_TEXT]; | |
16800 edit->cursor_text_normal= table[NK_COLOR_EDIT]; | |
16801 edit->cursor_text_hover = table[NK_COLOR_EDIT]; | |
16802 edit->text_normal = table[NK_COLOR_TEXT]; | |
16803 edit->text_hover = table[NK_COLOR_TEXT]; | |
16804 edit->text_active = table[NK_COLOR_TEXT]; | |
16805 edit->selected_normal = table[NK_COLOR_TEXT]; | |
16806 edit->selected_hover = table[NK_COLOR_TEXT]; | |
16807 edit->selected_text_normal = table[NK_COLOR_EDIT]; | |
16808 edit->selected_text_hover = table[NK_COLOR_EDIT]; | |
16809 edit->padding = nk_vec2(0,0); | |
16810 edit->cursor_size = 8; | |
16811 edit->border = 0; | |
16812 edit->rounding = 0; | |
16813 | |
16814 /* chart */ | |
16815 chart = &style->chart; | |
16816 nk_zero_struct(*chart); | |
16817 chart->background = nk_style_item_color(table[NK_COLOR_CHART]); | |
16818 chart->border_color = table[NK_COLOR_BORDER]; | |
16819 chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; | |
16820 chart->color = table[NK_COLOR_CHART_COLOR]; | |
16821 chart->padding = nk_vec2(4,4); | |
16822 chart->border = 0; | |
16823 chart->rounding = 0; | |
16824 | |
16825 /* combo */ | |
16826 combo = &style->combo; | |
16827 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16828 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16829 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16830 combo->border_color = table[NK_COLOR_BORDER]; | |
16831 combo->label_normal = table[NK_COLOR_TEXT]; | |
16832 combo->label_hover = table[NK_COLOR_TEXT]; | |
16833 combo->label_active = table[NK_COLOR_TEXT]; | |
16834 combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; | |
16835 combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; | |
16836 combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; | |
16837 combo->content_padding = nk_vec2(4,4); | |
16838 combo->button_padding = nk_vec2(0,4); | |
16839 combo->spacing = nk_vec2(4,0); | |
16840 combo->border = 1; | |
16841 combo->rounding = 0; | |
16842 | |
16843 /* combo button */ | |
16844 button = &style->combo.button; | |
16845 nk_zero_struct(*button); | |
16846 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16847 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16848 button->active = nk_style_item_color(table[NK_COLOR_COMBO]); | |
16849 button->border_color = nk_rgba(0,0,0,0); | |
16850 button->text_background = table[NK_COLOR_COMBO]; | |
16851 button->text_normal = table[NK_COLOR_TEXT]; | |
16852 button->text_hover = table[NK_COLOR_TEXT]; | |
16853 button->text_active = table[NK_COLOR_TEXT]; | |
16854 button->padding = nk_vec2(2.0f,2.0f); | |
16855 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16856 button->userdata = nk_handle_ptr(0); | |
16857 button->text_alignment = NK_TEXT_CENTERED; | |
16858 button->border = 0.0f; | |
16859 button->rounding = 0.0f; | |
16860 button->draw_begin = 0; | |
16861 button->draw_end = 0; | |
16862 | |
16863 /* tab */ | |
16864 tab = &style->tab; | |
16865 tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); | |
16866 tab->border_color = table[NK_COLOR_BORDER]; | |
16867 tab->text = table[NK_COLOR_TEXT]; | |
16868 tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; | |
16869 tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; | |
16870 tab->padding = nk_vec2(4,4); | |
16871 tab->spacing = nk_vec2(4,4); | |
16872 tab->indent = 10.0f; | |
16873 tab->border = 1; | |
16874 tab->rounding = 0; | |
16875 | |
16876 /* tab button */ | |
16877 button = &style->tab.tab_minimize_button; | |
16878 nk_zero_struct(*button); | |
16879 button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); | |
16880 button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); | |
16881 button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); | |
16882 button->border_color = nk_rgba(0,0,0,0); | |
16883 button->text_background = table[NK_COLOR_TAB_HEADER]; | |
16884 button->text_normal = table[NK_COLOR_TEXT]; | |
16885 button->text_hover = table[NK_COLOR_TEXT]; | |
16886 button->text_active = table[NK_COLOR_TEXT]; | |
16887 button->padding = nk_vec2(2.0f,2.0f); | |
16888 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16889 button->userdata = nk_handle_ptr(0); | |
16890 button->text_alignment = NK_TEXT_CENTERED; | |
16891 button->border = 0.0f; | |
16892 button->rounding = 0.0f; | |
16893 button->draw_begin = 0; | |
16894 button->draw_end = 0; | |
16895 style->tab.tab_maximize_button =*button; | |
16896 | |
16897 /* node button */ | |
16898 button = &style->tab.node_minimize_button; | |
16899 nk_zero_struct(*button); | |
16900 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16901 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16902 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16903 button->border_color = nk_rgba(0,0,0,0); | |
16904 button->text_background = table[NK_COLOR_TAB_HEADER]; | |
16905 button->text_normal = table[NK_COLOR_TEXT]; | |
16906 button->text_hover = table[NK_COLOR_TEXT]; | |
16907 button->text_active = table[NK_COLOR_TEXT]; | |
16908 button->padding = nk_vec2(2.0f,2.0f); | |
16909 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16910 button->userdata = nk_handle_ptr(0); | |
16911 button->text_alignment = NK_TEXT_CENTERED; | |
16912 button->border = 0.0f; | |
16913 button->rounding = 0.0f; | |
16914 button->draw_begin = 0; | |
16915 button->draw_end = 0; | |
16916 style->tab.node_maximize_button =*button; | |
16917 | |
16918 /* window header */ | |
16919 win = &style->window; | |
16920 win->header.align = NK_HEADER_RIGHT; | |
16921 win->header.close_symbol = NK_SYMBOL_X; | |
16922 win->header.minimize_symbol = NK_SYMBOL_MINUS; | |
16923 win->header.maximize_symbol = NK_SYMBOL_PLUS; | |
16924 win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16925 win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16926 win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16927 win->header.label_normal = table[NK_COLOR_TEXT]; | |
16928 win->header.label_hover = table[NK_COLOR_TEXT]; | |
16929 win->header.label_active = table[NK_COLOR_TEXT]; | |
16930 win->header.label_padding = nk_vec2(4,4); | |
16931 win->header.padding = nk_vec2(4,4); | |
16932 win->header.spacing = nk_vec2(0,0); | |
16933 | |
16934 /* window header close button */ | |
16935 button = &style->window.header.close_button; | |
16936 nk_zero_struct(*button); | |
16937 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16938 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16939 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16940 button->border_color = nk_rgba(0,0,0,0); | |
16941 button->text_background = table[NK_COLOR_HEADER]; | |
16942 button->text_normal = table[NK_COLOR_TEXT]; | |
16943 button->text_hover = table[NK_COLOR_TEXT]; | |
16944 button->text_active = table[NK_COLOR_TEXT]; | |
16945 button->padding = nk_vec2(0.0f,0.0f); | |
16946 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16947 button->userdata = nk_handle_ptr(0); | |
16948 button->text_alignment = NK_TEXT_CENTERED; | |
16949 button->border = 0.0f; | |
16950 button->rounding = 0.0f; | |
16951 button->draw_begin = 0; | |
16952 button->draw_end = 0; | |
16953 | |
16954 /* window header minimize button */ | |
16955 button = &style->window.header.minimize_button; | |
16956 nk_zero_struct(*button); | |
16957 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16958 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16959 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); | |
16960 button->border_color = nk_rgba(0,0,0,0); | |
16961 button->text_background = table[NK_COLOR_HEADER]; | |
16962 button->text_normal = table[NK_COLOR_TEXT]; | |
16963 button->text_hover = table[NK_COLOR_TEXT]; | |
16964 button->text_active = table[NK_COLOR_TEXT]; | |
16965 button->padding = nk_vec2(0.0f,0.0f); | |
16966 button->touch_padding = nk_vec2(0.0f,0.0f); | |
16967 button->userdata = nk_handle_ptr(0); | |
16968 button->text_alignment = NK_TEXT_CENTERED; | |
16969 button->border = 0.0f; | |
16970 button->rounding = 0.0f; | |
16971 button->draw_begin = 0; | |
16972 button->draw_end = 0; | |
16973 | |
16974 /* window */ | |
16975 win->background = table[NK_COLOR_WINDOW]; | |
16976 win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); | |
16977 win->border_color = table[NK_COLOR_BORDER]; | |
16978 win->popup_border_color = table[NK_COLOR_BORDER]; | |
16979 win->combo_border_color = table[NK_COLOR_BORDER]; | |
16980 win->contextual_border_color = table[NK_COLOR_BORDER]; | |
16981 win->menu_border_color = table[NK_COLOR_BORDER]; | |
16982 win->group_border_color = table[NK_COLOR_BORDER]; | |
16983 win->tooltip_border_color = table[NK_COLOR_BORDER]; | |
16984 win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); | |
16985 | |
16986 win->rounding = 0.0f; | |
16987 win->spacing = nk_vec2(4,4); | |
16988 win->scrollbar_size = nk_vec2(10,10); | |
16989 win->min_size = nk_vec2(64,64); | |
16990 | |
16991 win->combo_border = 1.0f; | |
16992 win->contextual_border = 1.0f; | |
16993 win->menu_border = 1.0f; | |
16994 win->group_border = 1.0f; | |
16995 win->tooltip_border = 1.0f; | |
16996 win->popup_border = 1.0f; | |
16997 win->border = 2.0f; | |
16998 win->min_row_height_padding = 8; | |
16999 | |
17000 win->padding = nk_vec2(4,4); | |
17001 win->group_padding = nk_vec2(4,4); | |
17002 win->popup_padding = nk_vec2(4,4); | |
17003 win->combo_padding = nk_vec2(4,4); | |
17004 win->contextual_padding = nk_vec2(4,4); | |
17005 win->menu_padding = nk_vec2(4,4); | |
17006 win->tooltip_padding = nk_vec2(4,4); | |
17007 } | |
17008 | |
17009 NK_API void | |
17010 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) | |
17011 { | |
17012 struct nk_style *style; | |
17013 NK_ASSERT(ctx); | |
17014 | |
17015 if (!ctx) return; | |
17016 style = &ctx->style; | |
17017 style->font = font; | |
17018 ctx->stacks.fonts.head = 0; | |
17019 if (ctx->current) | |
17020 nk_layout_reset_min_row_height(ctx); | |
17021 } | |
17022 | |
17023 NK_API int | |
17024 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font) | |
17025 { | |
17026 struct nk_config_stack_user_font *font_stack; | |
17027 struct nk_config_stack_user_font_element *element; | |
17028 | |
17029 NK_ASSERT(ctx); | |
17030 if (!ctx) return 0; | |
17031 | |
17032 font_stack = &ctx->stacks.fonts; | |
17033 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); | |
17034 if (font_stack->head >= (int)NK_LEN(font_stack->elements)) | |
17035 return 0; | |
17036 | |
17037 element = &font_stack->elements[font_stack->head++]; | |
17038 element->address = &ctx->style.font; | |
17039 element->old_value = ctx->style.font; | |
17040 ctx->style.font = font; | |
17041 return 1; | |
17042 } | |
17043 | |
17044 NK_API int | |
17045 nk_style_pop_font(struct nk_context *ctx) | |
17046 { | |
17047 struct nk_config_stack_user_font *font_stack; | |
17048 struct nk_config_stack_user_font_element *element; | |
17049 | |
17050 NK_ASSERT(ctx); | |
17051 if (!ctx) return 0; | |
17052 | |
17053 font_stack = &ctx->stacks.fonts; | |
17054 NK_ASSERT(font_stack->head > 0); | |
17055 if (font_stack->head < 1) | |
17056 return 0; | |
17057 | |
17058 element = &font_stack->elements[--font_stack->head]; | |
17059 *element->address = element->old_value; | |
17060 return 1; | |
17061 } | |
17062 | |
17063 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ | |
17064 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ | |
17065 {\ | |
17066 struct nk_config_stack_##type * type_stack;\ | |
17067 struct nk_config_stack_##type##_element *element;\ | |
17068 NK_ASSERT(ctx);\ | |
17069 if (!ctx) return 0;\ | |
17070 type_stack = &ctx->stacks.stack;\ | |
17071 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ | |
17072 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ | |
17073 return 0;\ | |
17074 element = &type_stack->elements[type_stack->head++];\ | |
17075 element->address = address;\ | |
17076 element->old_value = *address;\ | |
17077 *address = value;\ | |
17078 return 1;\ | |
17079 } | |
17080 | |
17081 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \ | |
17082 nk_style_pop_##type(struct nk_context *ctx)\ | |
17083 {\ | |
17084 struct nk_config_stack_##type *type_stack;\ | |
17085 struct nk_config_stack_##type##_element *element;\ | |
17086 NK_ASSERT(ctx);\ | |
17087 if (!ctx) return 0;\ | |
17088 type_stack = &ctx->stacks.stack;\ | |
17089 NK_ASSERT(type_stack->head > 0);\ | |
17090 if (type_stack->head < 1)\ | |
17091 return 0;\ | |
17092 element = &type_stack->elements[--type_stack->head];\ | |
17093 *element->address = element->old_value;\ | |
17094 return 1;\ | |
17095 } | |
17096 | |
17097 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) | |
17098 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) | |
17099 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) | |
17100 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) | |
17101 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) | |
17102 | |
17103 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items) | |
17104 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats) | |
17105 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors) | |
17106 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags) | |
17107 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors) | |
17108 | |
17109 NK_API int | |
17110 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) | |
17111 { | |
17112 struct nk_style *style; | |
17113 NK_ASSERT(ctx); | |
17114 if (!ctx) return 0; | |
17115 style = &ctx->style; | |
17116 if (style->cursors[c]) { | |
17117 style->cursor_active = style->cursors[c]; | |
17118 return 1; | |
17119 } | |
17120 return 0; | |
17121 } | |
17122 | |
17123 NK_API void | |
17124 nk_style_show_cursor(struct nk_context *ctx) | |
17125 { | |
17126 ctx->style.cursor_visible = nk_true; | |
17127 } | |
17128 | |
17129 NK_API void | |
17130 nk_style_hide_cursor(struct nk_context *ctx) | |
17131 { | |
17132 ctx->style.cursor_visible = nk_false; | |
17133 } | |
17134 | |
17135 NK_API void | |
17136 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, | |
17137 const struct nk_cursor *c) | |
17138 { | |
17139 struct nk_style *style; | |
17140 NK_ASSERT(ctx); | |
17141 if (!ctx) return; | |
17142 style = &ctx->style; | |
17143 style->cursors[cursor] = c; | |
17144 } | |
17145 | |
17146 NK_API void | |
17147 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) | |
17148 { | |
17149 int i = 0; | |
17150 struct nk_style *style; | |
17151 NK_ASSERT(ctx); | |
17152 if (!ctx) return; | |
17153 style = &ctx->style; | |
17154 for (i = 0; i < NK_CURSOR_COUNT; ++i) | |
17155 style->cursors[i] = &cursors[i]; | |
17156 style->cursor_visible = nk_true; | |
17157 } | |
17158 | |
17159 /* =============================================================== | |
17160 * | |
17161 * POOL | |
17162 * | |
17163 * ===============================================================*/ | |
17164 NK_INTERN void | |
17165 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, | |
17166 unsigned int capacity) | |
17167 { | |
17168 nk_zero(pool, sizeof(*pool)); | |
17169 pool->alloc = *alloc; | |
17170 pool->capacity = capacity; | |
17171 pool->type = NK_BUFFER_DYNAMIC; | |
17172 pool->pages = 0; | |
17173 } | |
17174 | |
17175 NK_INTERN void | |
17176 nk_pool_free(struct nk_pool *pool) | |
17177 { | |
17178 struct nk_page *iter = pool->pages; | |
17179 if (!pool) return; | |
17180 if (pool->type == NK_BUFFER_FIXED) return; | |
17181 while (iter) { | |
17182 struct nk_page *next = iter->next; | |
17183 pool->alloc.free(pool->alloc.userdata, iter); | |
17184 iter = next; | |
17185 } | |
17186 } | |
17187 | |
17188 NK_INTERN void | |
17189 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) | |
17190 { | |
17191 nk_zero(pool, sizeof(*pool)); | |
17192 NK_ASSERT(size >= sizeof(struct nk_page)); | |
17193 if (size < sizeof(struct nk_page)) return; | |
17194 pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element); | |
17195 pool->pages = (struct nk_page*)memory; | |
17196 pool->type = NK_BUFFER_FIXED; | |
17197 pool->size = size; | |
17198 } | |
17199 | |
17200 NK_INTERN struct nk_page_element* | |
17201 nk_pool_alloc(struct nk_pool *pool) | |
17202 { | |
17203 if (!pool->pages || pool->pages->size >= pool->capacity) { | |
17204 /* allocate new page */ | |
17205 struct nk_page *page; | |
17206 if (pool->type == NK_BUFFER_FIXED) { | |
17207 if (!pool->pages) { | |
17208 NK_ASSERT(pool->pages); | |
17209 return 0; | |
17210 } | |
17211 NK_ASSERT(pool->pages->size < pool->capacity); | |
17212 return 0; | |
17213 } else { | |
17214 nk_size size = sizeof(struct nk_page); | |
17215 size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data); | |
17216 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); | |
17217 page->next = pool->pages; | |
17218 pool->pages = page; | |
17219 page->size = 0; | |
17220 } | |
17221 } | |
17222 return &pool->pages->win[pool->pages->size++]; | |
17223 } | |
17224 | |
17225 /* =============================================================== | |
17226 * | |
17227 * CONTEXT | |
17228 * | |
17229 * ===============================================================*/ | |
17230 NK_INTERN void* nk_create_window(struct nk_context *ctx); | |
17231 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*); | |
17232 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win); | |
17233 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); | |
17234 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl); | |
17235 NK_INTERN void* nk_create_panel(struct nk_context *ctx); | |
17236 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan); | |
17237 | |
17238 NK_INTERN void | |
17239 nk_setup(struct nk_context *ctx, const struct nk_user_font *font) | |
17240 { | |
17241 NK_ASSERT(ctx); | |
17242 if (!ctx) return; | |
17243 nk_zero_struct(*ctx); | |
17244 nk_style_default(ctx); | |
17245 ctx->seq = 1; | |
17246 if (font) ctx->style.font = font; | |
17247 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
17248 nk_draw_list_init(&ctx->draw_list); | |
17249 #endif | |
17250 } | |
17251 | |
17252 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR | |
17253 NK_API int | |
17254 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) | |
17255 { | |
17256 struct nk_allocator alloc; | |
17257 alloc.userdata.ptr = 0; | |
17258 alloc.alloc = nk_malloc; | |
17259 alloc.free = nk_mfree; | |
17260 return nk_init(ctx, &alloc, font); | |
17261 } | |
17262 #endif | |
17263 | |
17264 NK_API int | |
17265 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, | |
17266 const struct nk_user_font *font) | |
17267 { | |
17268 NK_ASSERT(memory); | |
17269 if (!memory) return 0; | |
17270 nk_setup(ctx, font); | |
17271 nk_buffer_init_fixed(&ctx->memory, memory, size); | |
17272 ctx->use_pool = nk_false; | |
17273 return 1; | |
17274 } | |
17275 | |
17276 NK_API int | |
17277 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, | |
17278 struct nk_buffer *pool, const struct nk_user_font *font) | |
17279 { | |
17280 NK_ASSERT(cmds); | |
17281 NK_ASSERT(pool); | |
17282 if (!cmds || !pool) return 0; | |
17283 | |
17284 nk_setup(ctx, font); | |
17285 ctx->memory = *cmds; | |
17286 if (pool->type == NK_BUFFER_FIXED) { | |
17287 /* take memory from buffer and alloc fixed pool */ | |
17288 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); | |
17289 } else { | |
17290 /* create dynamic pool from buffer allocator */ | |
17291 struct nk_allocator *alloc = &pool->pool; | |
17292 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); | |
17293 } | |
17294 ctx->use_pool = nk_true; | |
17295 return 1; | |
17296 } | |
17297 | |
17298 NK_API int | |
17299 nk_init(struct nk_context *ctx, struct nk_allocator *alloc, | |
17300 const struct nk_user_font *font) | |
17301 { | |
17302 NK_ASSERT(alloc); | |
17303 if (!alloc) return 0; | |
17304 nk_setup(ctx, font); | |
17305 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); | |
17306 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); | |
17307 ctx->use_pool = nk_true; | |
17308 return 1; | |
17309 } | |
17310 | |
17311 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
17312 NK_API void | |
17313 nk_set_user_data(struct nk_context *ctx, nk_handle handle) | |
17314 { | |
17315 if (!ctx) return; | |
17316 ctx->userdata = handle; | |
17317 if (ctx->current) | |
17318 ctx->current->buffer.userdata = handle; | |
17319 } | |
17320 #endif | |
17321 | |
17322 NK_API void | |
17323 nk_free(struct nk_context *ctx) | |
17324 { | |
17325 NK_ASSERT(ctx); | |
17326 if (!ctx) return; | |
17327 nk_buffer_free(&ctx->memory); | |
17328 if (ctx->use_pool) | |
17329 nk_pool_free(&ctx->pool); | |
17330 | |
17331 nk_zero(&ctx->input, sizeof(ctx->input)); | |
17332 nk_zero(&ctx->style, sizeof(ctx->style)); | |
17333 nk_zero(&ctx->memory, sizeof(ctx->memory)); | |
17334 | |
17335 ctx->seq = 0; | |
17336 ctx->build = 0; | |
17337 ctx->begin = 0; | |
17338 ctx->end = 0; | |
17339 ctx->active = 0; | |
17340 ctx->current = 0; | |
17341 ctx->freelist = 0; | |
17342 ctx->count = 0; | |
17343 } | |
17344 | |
17345 NK_API void | |
17346 nk_clear(struct nk_context *ctx) | |
17347 { | |
17348 struct nk_window *iter; | |
17349 struct nk_window *next; | |
17350 NK_ASSERT(ctx); | |
17351 | |
17352 if (!ctx) return; | |
17353 if (ctx->use_pool) | |
17354 nk_buffer_clear(&ctx->memory); | |
17355 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); | |
17356 | |
17357 ctx->build = 0; | |
17358 ctx->memory.calls = 0; | |
17359 ctx->last_widget_state = 0; | |
17360 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; | |
17361 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); | |
17362 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT | |
17363 nk_draw_list_clear(&ctx->draw_list); | |
17364 #endif | |
17365 | |
17366 /* garbage collector */ | |
17367 iter = ctx->begin; | |
17368 while (iter) { | |
17369 /* make sure minimized windows do not get removed */ | |
17370 if ((iter->flags & NK_WINDOW_MINIMIZED) && | |
17371 !(iter->flags & NK_WINDOW_CLOSED)) { | |
17372 iter = iter->next; | |
17373 continue; | |
17374 } | |
17375 /* remove hotness from hidden or closed windows*/ | |
17376 if (((iter->flags & NK_WINDOW_HIDDEN) || | |
17377 (iter->flags & NK_WINDOW_CLOSED)) && | |
17378 iter == ctx->active) { | |
17379 ctx->active = iter->prev; | |
17380 ctx->end = iter->prev; | |
17381 if (ctx->active) | |
17382 ctx->active->flags &= ~NK_WINDOW_ROM; | |
17383 } | |
17384 | |
17385 /* free unused popup windows */ | |
17386 if (iter->popup.win && iter->popup.win->seq != ctx->seq) { | |
17387 nk_free_window(ctx, iter->popup.win); | |
17388 iter->popup.win = 0; | |
17389 } | |
17390 /* remove unused window state tables */ | |
17391 {struct nk_table *n, *it = iter->tables; | |
17392 while (it) { | |
17393 n = it->next; | |
17394 if (it->seq != ctx->seq) { | |
17395 nk_remove_table(iter, it); | |
17396 nk_zero(it, sizeof(union nk_page_data)); | |
17397 nk_free_table(ctx, it); | |
17398 if (it == iter->tables) | |
17399 iter->tables = n; | |
17400 } | |
17401 it = n; | |
17402 }} | |
17403 /* window itself is not used anymore so free */ | |
17404 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { | |
17405 next = iter->next; | |
17406 nk_remove_window(ctx, iter); | |
17407 nk_free_window(ctx, iter); | |
17408 iter = next; | |
17409 } else iter = iter->next; | |
17410 } | |
17411 ctx->seq++; | |
17412 } | |
17413 | |
17414 /* ---------------------------------------------------------------- | |
17415 * | |
17416 * BUFFERING | |
17417 * | |
17418 * ---------------------------------------------------------------*/ | |
17419 NK_INTERN void | |
17420 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) | |
17421 { | |
17422 NK_ASSERT(ctx); | |
17423 NK_ASSERT(buffer); | |
17424 if (!ctx || !buffer) return; | |
17425 buffer->begin = ctx->memory.allocated; | |
17426 buffer->end = buffer->begin; | |
17427 buffer->last = buffer->begin; | |
17428 buffer->clip = nk_null_rect; | |
17429 } | |
17430 | |
17431 NK_INTERN void | |
17432 nk_start(struct nk_context *ctx, struct nk_window *win) | |
17433 { | |
17434 NK_ASSERT(ctx); | |
17435 NK_ASSERT(win); | |
17436 nk_start_buffer(ctx, &win->buffer); | |
17437 } | |
17438 | |
17439 NK_INTERN void | |
17440 nk_start_popup(struct nk_context *ctx, struct nk_window *win) | |
17441 { | |
17442 struct nk_popup_buffer *buf; | |
17443 NK_ASSERT(ctx); | |
17444 NK_ASSERT(win); | |
17445 if (!ctx || !win) return; | |
17446 | |
17447 /* save buffer fill state for popup */ | |
17448 buf = &win->popup.buf; | |
17449 buf->begin = win->buffer.end; | |
17450 buf->end = win->buffer.end; | |
17451 buf->parent = win->buffer.last; | |
17452 buf->last = buf->begin; | |
17453 buf->active = nk_true; | |
17454 } | |
17455 | |
17456 NK_INTERN void | |
17457 nk_finish_popup(struct nk_context *ctx, struct nk_window *win) | |
17458 { | |
17459 struct nk_popup_buffer *buf; | |
17460 NK_ASSERT(ctx); | |
17461 NK_ASSERT(win); | |
17462 if (!ctx || !win) return; | |
17463 | |
17464 buf = &win->popup.buf; | |
17465 buf->last = win->buffer.last; | |
17466 buf->end = win->buffer.end; | |
17467 } | |
17468 | |
17469 NK_INTERN void | |
17470 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) | |
17471 { | |
17472 NK_ASSERT(ctx); | |
17473 NK_ASSERT(buffer); | |
17474 if (!ctx || !buffer) return; | |
17475 buffer->end = ctx->memory.allocated; | |
17476 } | |
17477 | |
17478 NK_INTERN void | |
17479 nk_finish(struct nk_context *ctx, struct nk_window *win) | |
17480 { | |
17481 struct nk_popup_buffer *buf; | |
17482 struct nk_command *parent_last; | |
17483 void *memory; | |
17484 | |
17485 NK_ASSERT(ctx); | |
17486 NK_ASSERT(win); | |
17487 if (!ctx || !win) return; | |
17488 nk_finish_buffer(ctx, &win->buffer); | |
17489 if (!win->popup.buf.active) return; | |
17490 | |
17491 buf = &win->popup.buf; | |
17492 memory = ctx->memory.memory.ptr; | |
17493 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); | |
17494 parent_last->next = buf->end; | |
17495 } | |
17496 | |
17497 NK_INTERN void | |
17498 nk_build(struct nk_context *ctx) | |
17499 { | |
17500 struct nk_window *iter = 0; | |
17501 struct nk_command *cmd = 0; | |
17502 nk_byte *buffer = 0; | |
17503 | |
17504 /* draw cursor overlay */ | |
17505 if (!ctx->style.cursor_active) | |
17506 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; | |
17507 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { | |
17508 struct nk_rect mouse_bounds; | |
17509 const struct nk_cursor *cursor = ctx->style.cursor_active; | |
17510 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); | |
17511 nk_start_buffer(ctx, &ctx->overlay); | |
17512 | |
17513 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; | |
17514 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; | |
17515 mouse_bounds.w = cursor->size.x; | |
17516 mouse_bounds.h = cursor->size.y; | |
17517 | |
17518 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); | |
17519 nk_finish_buffer(ctx, &ctx->overlay); | |
17520 } | |
17521 /* build one big draw command list out of all window buffers */ | |
17522 iter = ctx->begin; | |
17523 buffer = (nk_byte*)ctx->memory.memory.ptr; | |
17524 while (iter != 0) { | |
17525 struct nk_window *next = iter->next; | |
17526 if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN)|| | |
17527 iter->seq != ctx->seq) | |
17528 goto cont; | |
17529 | |
17530 cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last); | |
17531 while (next && ((next->buffer.last == next->buffer.begin) || | |
17532 (next->flags & NK_WINDOW_HIDDEN))) | |
17533 next = next->next; /* skip empty command buffers */ | |
17534 | |
17535 if (next) cmd->next = next->buffer.begin; | |
17536 cont: iter = next; | |
17537 } | |
17538 /* append all popup draw commands into lists */ | |
17539 iter = ctx->begin; | |
17540 while (iter != 0) { | |
17541 struct nk_window *next = iter->next; | |
17542 struct nk_popup_buffer *buf; | |
17543 if (!iter->popup.buf.active) | |
17544 goto skip; | |
17545 | |
17546 buf = &iter->popup.buf; | |
17547 cmd->next = buf->begin; | |
17548 cmd = nk_ptr_add(struct nk_command, buffer, buf->last); | |
17549 buf->active = nk_false; | |
17550 skip: iter = next; | |
17551 } | |
17552 /* append overlay commands */ | |
17553 if (cmd) { | |
17554 if (ctx->overlay.end != ctx->overlay.begin) | |
17555 cmd->next = ctx->overlay.begin; | |
17556 else cmd->next = ctx->memory.allocated; | |
17557 } | |
17558 } | |
17559 | |
17560 NK_API const struct nk_command* | |
17561 nk__begin(struct nk_context *ctx) | |
17562 { | |
17563 struct nk_window *iter; | |
17564 nk_byte *buffer; | |
17565 NK_ASSERT(ctx); | |
17566 if (!ctx) return 0; | |
17567 if (!ctx->count) return 0; | |
17568 | |
17569 buffer = (nk_byte*)ctx->memory.memory.ptr; | |
17570 if (!ctx->build) { | |
17571 nk_build(ctx); | |
17572 ctx->build = nk_true; | |
17573 } | |
17574 iter = ctx->begin; | |
17575 while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN))) | |
17576 iter = iter->next; | |
17577 if (!iter) return 0; | |
17578 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); | |
17579 } | |
17580 | |
17581 NK_API const struct nk_command* | |
17582 nk__next(struct nk_context *ctx, const struct nk_command *cmd) | |
17583 { | |
17584 nk_byte *buffer; | |
17585 const struct nk_command *next; | |
17586 NK_ASSERT(ctx); | |
17587 if (!ctx || !cmd || !ctx->count) return 0; | |
17588 if (cmd->next >= ctx->memory.allocated) return 0; | |
17589 buffer = (nk_byte*)ctx->memory.memory.ptr; | |
17590 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); | |
17591 return next; | |
17592 } | |
17593 | |
17594 /* ---------------------------------------------------------------- | |
17595 * | |
17596 * PANEL | |
17597 * | |
17598 * ---------------------------------------------------------------*/ | |
17599 static int | |
17600 nk_panel_has_header(nk_flags flags, const char *title) | |
17601 { | |
17602 int active = 0; | |
17603 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); | |
17604 active = active || (flags & NK_WINDOW_TITLE); | |
17605 active = active && !(flags & NK_WINDOW_HIDDEN) && title; | |
17606 return active; | |
17607 } | |
17608 | |
17609 NK_INTERN struct nk_vec2 | |
17610 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) | |
17611 { | |
17612 switch (type) { | |
17613 default: | |
17614 case NK_PANEL_WINDOW: return style->window.padding; | |
17615 case NK_PANEL_GROUP: return style->window.group_padding; | |
17616 case NK_PANEL_POPUP: return style->window.popup_padding; | |
17617 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; | |
17618 case NK_PANEL_COMBO: return style->window.combo_padding; | |
17619 case NK_PANEL_MENU: return style->window.menu_padding; | |
17620 case NK_PANEL_TOOLTIP: return style->window.menu_padding; | |
17621 } | |
17622 } | |
17623 | |
17624 NK_INTERN float | |
17625 nk_panel_get_border(const struct nk_style *style, nk_flags flags, | |
17626 enum nk_panel_type type) | |
17627 { | |
17628 if (flags & NK_WINDOW_BORDER) { | |
17629 switch (type) { | |
17630 default: | |
17631 case NK_PANEL_WINDOW: return style->window.border; | |
17632 case NK_PANEL_GROUP: return style->window.group_border; | |
17633 case NK_PANEL_POPUP: return style->window.popup_border; | |
17634 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; | |
17635 case NK_PANEL_COMBO: return style->window.combo_border; | |
17636 case NK_PANEL_MENU: return style->window.menu_border; | |
17637 case NK_PANEL_TOOLTIP: return style->window.menu_border; | |
17638 }} else return 0; | |
17639 } | |
17640 | |
17641 NK_INTERN struct nk_color | |
17642 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) | |
17643 { | |
17644 switch (type) { | |
17645 default: | |
17646 case NK_PANEL_WINDOW: return style->window.border_color; | |
17647 case NK_PANEL_GROUP: return style->window.group_border_color; | |
17648 case NK_PANEL_POPUP: return style->window.popup_border_color; | |
17649 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; | |
17650 case NK_PANEL_COMBO: return style->window.combo_border_color; | |
17651 case NK_PANEL_MENU: return style->window.menu_border_color; | |
17652 case NK_PANEL_TOOLTIP: return style->window.menu_border_color; | |
17653 } | |
17654 } | |
17655 | |
17656 NK_INTERN int | |
17657 nk_panel_is_sub(enum nk_panel_type type) | |
17658 { | |
17659 return (type & NK_PANEL_SET_SUB)?1:0; | |
17660 } | |
17661 | |
17662 NK_INTERN int | |
17663 nk_panel_is_nonblock(enum nk_panel_type type) | |
17664 { | |
17665 return (type & NK_PANEL_SET_NONBLOCK)?1:0; | |
17666 } | |
17667 | |
17668 NK_INTERN int | |
17669 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) | |
17670 { | |
17671 struct nk_input *in; | |
17672 struct nk_window *win; | |
17673 struct nk_panel *layout; | |
17674 struct nk_command_buffer *out; | |
17675 const struct nk_style *style; | |
17676 const struct nk_user_font *font; | |
17677 | |
17678 struct nk_vec2 scrollbar_size; | |
17679 struct nk_vec2 panel_padding; | |
17680 | |
17681 NK_ASSERT(ctx); | |
17682 NK_ASSERT(ctx->current); | |
17683 NK_ASSERT(ctx->current->layout); | |
17684 if (!ctx || !ctx->current || !ctx->current->layout) return 0; | |
17685 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); | |
17686 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) { | |
17687 nk_zero(ctx->current->layout, sizeof(struct nk_panel)); | |
17688 ctx->current->layout->type = panel_type; | |
17689 return 0; | |
17690 } | |
17691 /* pull state into local stack */ | |
17692 style = &ctx->style; | |
17693 font = style->font; | |
17694 win = ctx->current; | |
17695 layout = win->layout; | |
17696 out = &win->buffer; | |
17697 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input; | |
17698 #ifdef NK_INCLUDE_COMMAND_USERDATA | |
17699 win->buffer.userdata = ctx->userdata; | |
17700 #endif | |
17701 /* pull style configuration into local stack */ | |
17702 scrollbar_size = style->window.scrollbar_size; | |
17703 panel_padding = nk_panel_get_padding(style, panel_type); | |
17704 | |
17705 /* window movement */ | |
17706 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { | |
17707 int left_mouse_down; | |
17708 int left_mouse_click_in_cursor; | |
17709 | |
17710 /* calculate draggable window space */ | |
17711 struct nk_rect header; | |
17712 header.x = win->bounds.x; | |
17713 header.y = win->bounds.y; | |
17714 header.w = win->bounds.w; | |
17715 if (nk_panel_has_header(win->flags, title)) { | |
17716 header.h = font->height + 2.0f * style->window.header.padding.y; | |
17717 header.h += 2.0f * style->window.header.label_padding.y; | |
17718 } else header.h = panel_padding.y; | |
17719 | |
17720 /* window movement by dragging */ | |
17721 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; | |
17722 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, | |
17723 NK_BUTTON_LEFT, header, nk_true); | |
17724 if (left_mouse_down && left_mouse_click_in_cursor) { | |
17725 win->bounds.x = win->bounds.x + in->mouse.delta.x; | |
17726 win->bounds.y = win->bounds.y + in->mouse.delta.y; | |
17727 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; | |
17728 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; | |
17729 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; | |
17730 } | |
17731 } | |
17732 | |
17733 /* setup panel */ | |
17734 layout->type = panel_type; | |
17735 layout->flags = win->flags; | |
17736 layout->bounds = win->bounds; | |
17737 layout->bounds.x += panel_padding.x; | |
17738 layout->bounds.w -= 2*panel_padding.x; | |
17739 if (win->flags & NK_WINDOW_BORDER) { | |
17740 layout->border = nk_panel_get_border(style, win->flags, panel_type); | |
17741 layout->bounds = nk_shrink_rect(layout->bounds, layout->border); | |
17742 } else layout->border = 0; | |
17743 layout->at_y = layout->bounds.y; | |
17744 layout->at_x = layout->bounds.x; | |
17745 layout->max_x = 0; | |
17746 layout->header_height = 0; | |
17747 layout->footer_height = 0; | |
17748 nk_layout_reset_min_row_height(ctx); | |
17749 layout->row.index = 0; | |
17750 layout->row.columns = 0; | |
17751 layout->row.ratio = 0; | |
17752 layout->row.item_width = 0; | |
17753 layout->row.tree_depth = 0; | |
17754 layout->row.height = panel_padding.y; | |
17755 layout->has_scrolling = nk_true; | |
17756 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) | |
17757 layout->bounds.w -= scrollbar_size.x; | |
17758 if (!nk_panel_is_nonblock(panel_type)) { | |
17759 layout->footer_height = 0; | |
17760 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) | |
17761 layout->footer_height = scrollbar_size.y; | |
17762 layout->bounds.h -= layout->footer_height; | |
17763 } | |
17764 | |
17765 /* panel header */ | |
17766 if (nk_panel_has_header(win->flags, title)) | |
17767 { | |
17768 struct nk_text text; | |
17769 struct nk_rect header; | |
17770 const struct nk_style_item *background = 0; | |
17771 | |
17772 /* calculate header bounds */ | |
17773 header.x = win->bounds.x; | |
17774 header.y = win->bounds.y; | |
17775 header.w = win->bounds.w; | |
17776 header.h = font->height + 2.0f * style->window.header.padding.y; | |
17777 header.h += (2.0f * style->window.header.label_padding.y); | |
17778 | |
17779 /* shrink panel by header */ | |
17780 layout->header_height = header.h; | |
17781 layout->bounds.y += header.h; | |
17782 layout->bounds.h -= header.h; | |
17783 layout->at_y += header.h; | |
17784 | |
17785 /* select correct header background and text color */ | |
17786 if (ctx->active == win) { | |
17787 background = &style->window.header.active; | |
17788 text.text = style->window.header.label_active; | |
17789 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { | |
17790 background = &style->window.header.hover; | |
17791 text.text = style->window.header.label_hover; | |
17792 } else { | |
17793 background = &style->window.header.normal; | |
17794 text.text = style->window.header.label_normal; | |
17795 } | |
17796 | |
17797 /* draw header background */ | |
17798 header.h += 1.0f; | |
17799 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
17800 text.background = nk_rgba(0,0,0,0); | |
17801 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
17802 } else { | |
17803 text.background = background->data.color; | |
17804 nk_fill_rect(out, header, 0, background->data.color); | |
17805 } | |
17806 | |
17807 /* window close button */ | |
17808 {struct nk_rect button; | |
17809 button.y = header.y + style->window.header.padding.y; | |
17810 button.h = header.h - 2 * style->window.header.padding.y; | |
17811 button.w = button.h; | |
17812 if (win->flags & NK_WINDOW_CLOSABLE) { | |
17813 nk_flags ws = 0; | |
17814 if (style->window.header.align == NK_HEADER_RIGHT) { | |
17815 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); | |
17816 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; | |
17817 } else { | |
17818 button.x = header.x + style->window.header.padding.x; | |
17819 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; | |
17820 } | |
17821 | |
17822 if (nk_do_button_symbol(&ws, &win->buffer, button, | |
17823 style->window.header.close_symbol, NK_BUTTON_DEFAULT, | |
17824 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) | |
17825 { | |
17826 layout->flags |= NK_WINDOW_HIDDEN; | |
17827 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; | |
17828 } | |
17829 } | |
17830 | |
17831 /* window minimize button */ | |
17832 if (win->flags & NK_WINDOW_MINIMIZABLE) { | |
17833 nk_flags ws = 0; | |
17834 if (style->window.header.align == NK_HEADER_RIGHT) { | |
17835 button.x = (header.w + header.x) - button.w; | |
17836 if (!(win->flags & NK_WINDOW_CLOSABLE)) { | |
17837 button.x -= style->window.header.padding.x; | |
17838 header.w -= style->window.header.padding.x; | |
17839 } | |
17840 header.w -= button.w + style->window.header.spacing.x; | |
17841 } else { | |
17842 button.x = header.x; | |
17843 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; | |
17844 } | |
17845 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? | |
17846 style->window.header.maximize_symbol: style->window.header.minimize_symbol, | |
17847 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) | |
17848 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? | |
17849 layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: | |
17850 layout->flags | NK_WINDOW_MINIMIZED; | |
17851 }} | |
17852 | |
17853 {/* window header title */ | |
17854 int text_len = nk_strlen(title); | |
17855 struct nk_rect label = {0,0,0,0}; | |
17856 float t = font->width(font->userdata, font->height, title, text_len); | |
17857 text.padding = nk_vec2(0,0); | |
17858 | |
17859 label.x = header.x + style->window.header.padding.x; | |
17860 label.x += style->window.header.label_padding.x; | |
17861 label.y = header.y + style->window.header.label_padding.y; | |
17862 label.h = font->height + 2 * style->window.header.label_padding.y; | |
17863 label.w = t + 2 * style->window.header.spacing.x; | |
17864 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x); | |
17865 nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);} | |
17866 } | |
17867 | |
17868 /* draw window background */ | |
17869 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { | |
17870 struct nk_rect body; | |
17871 body.x = win->bounds.x; | |
17872 body.w = win->bounds.w; | |
17873 body.y = (win->bounds.y + layout->header_height); | |
17874 body.h = (win->bounds.h - layout->header_height); | |
17875 if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE) | |
17876 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); | |
17877 else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); | |
17878 } | |
17879 | |
17880 /* set clipping rectangle */ | |
17881 {struct nk_rect clip; | |
17882 layout->clip = layout->bounds; | |
17883 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, | |
17884 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); | |
17885 nk_push_scissor(out, clip); | |
17886 layout->clip = clip;} | |
17887 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); | |
17888 } | |
17889 | |
17890 NK_INTERN void | |
17891 nk_panel_end(struct nk_context *ctx) | |
17892 { | |
17893 struct nk_input *in; | |
17894 struct nk_window *window; | |
17895 struct nk_panel *layout; | |
17896 const struct nk_style *style; | |
17897 struct nk_command_buffer *out; | |
17898 | |
17899 struct nk_vec2 scrollbar_size; | |
17900 struct nk_vec2 panel_padding; | |
17901 | |
17902 NK_ASSERT(ctx); | |
17903 NK_ASSERT(ctx->current); | |
17904 NK_ASSERT(ctx->current->layout); | |
17905 if (!ctx || !ctx->current || !ctx->current->layout) | |
17906 return; | |
17907 | |
17908 window = ctx->current; | |
17909 layout = window->layout; | |
17910 style = &ctx->style; | |
17911 out = &window->buffer; | |
17912 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input; | |
17913 if (!nk_panel_is_sub(layout->type)) | |
17914 nk_push_scissor(out, nk_null_rect); | |
17915 | |
17916 /* cache configuration data */ | |
17917 scrollbar_size = style->window.scrollbar_size; | |
17918 panel_padding = nk_panel_get_padding(style, layout->type); | |
17919 | |
17920 /* update the current cursor Y-position to point over the last added widget */ | |
17921 layout->at_y += layout->row.height; | |
17922 | |
17923 /* dynamic panels */ | |
17924 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) | |
17925 { | |
17926 /* update panel height to fit dynamic growth */ | |
17927 struct nk_rect empty_space; | |
17928 if (layout->at_y < (layout->bounds.y + layout->bounds.h)) | |
17929 layout->bounds.h = layout->at_y - layout->bounds.y; | |
17930 | |
17931 /* fill top empty space */ | |
17932 empty_space.x = window->bounds.x; | |
17933 empty_space.y = layout->bounds.y; | |
17934 empty_space.h = panel_padding.y; | |
17935 empty_space.w = window->bounds.w; | |
17936 nk_fill_rect(out, empty_space, 0, style->window.background); | |
17937 | |
17938 /* fill left empty space */ | |
17939 empty_space.x = window->bounds.x; | |
17940 empty_space.y = layout->bounds.y; | |
17941 empty_space.w = panel_padding.x + layout->border; | |
17942 empty_space.h = layout->bounds.h; | |
17943 nk_fill_rect(out, empty_space, 0, style->window.background); | |
17944 | |
17945 /* fill right empty space */ | |
17946 empty_space.x = layout->bounds.x + layout->bounds.w - layout->border; | |
17947 empty_space.y = layout->bounds.y; | |
17948 empty_space.w = panel_padding.x + layout->border; | |
17949 empty_space.h = layout->bounds.h; | |
17950 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) | |
17951 empty_space.w += scrollbar_size.x; | |
17952 nk_fill_rect(out, empty_space, 0, style->window.background); | |
17953 | |
17954 /* fill bottom empty space */ | |
17955 if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) { | |
17956 empty_space.x = window->bounds.x; | |
17957 empty_space.y = layout->bounds.y + layout->bounds.h; | |
17958 empty_space.w = window->bounds.w; | |
17959 empty_space.h = scrollbar_size.y; | |
17960 nk_fill_rect(out, empty_space, 0, style->window.background); | |
17961 } | |
17962 } | |
17963 | |
17964 /* scrollbars */ | |
17965 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && | |
17966 !(layout->flags & NK_WINDOW_MINIMIZED) && | |
17967 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) | |
17968 { | |
17969 struct nk_rect scroll; | |
17970 int scroll_has_scrolling; | |
17971 float scroll_target; | |
17972 float scroll_offset; | |
17973 float scroll_step; | |
17974 float scroll_inc; | |
17975 | |
17976 /* mouse wheel scrolling */ | |
17977 if (nk_panel_is_sub(layout->type)) | |
17978 { | |
17979 /* sub-window mouse wheel scrolling */ | |
17980 struct nk_window *root_window = window; | |
17981 struct nk_panel *root_panel = window->layout; | |
17982 while (root_panel->parent) | |
17983 root_panel = root_panel->parent; | |
17984 while (root_window->parent) | |
17985 root_window = root_window->parent; | |
17986 | |
17987 /* only allow scrolling if parent window is active */ | |
17988 scroll_has_scrolling = 0; | |
17989 if ((root_window == ctx->active) && layout->has_scrolling) { | |
17990 /* and panel is being hovered and inside clip rect*/ | |
17991 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && | |
17992 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, | |
17993 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) | |
17994 { | |
17995 /* deactivate all parent scrolling */ | |
17996 root_panel = window->layout; | |
17997 while (root_panel->parent) { | |
17998 root_panel->has_scrolling = nk_false; | |
17999 root_panel = root_panel->parent; | |
18000 } | |
18001 root_panel->has_scrolling = nk_false; | |
18002 scroll_has_scrolling = nk_true; | |
18003 } | |
18004 } | |
18005 } else if (!nk_panel_is_sub(layout->type)) { | |
18006 /* window mouse wheel scrolling */ | |
18007 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; | |
18008 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling) | |
18009 window->scrolled = nk_true; | |
18010 else window->scrolled = nk_false; | |
18011 } else scroll_has_scrolling = nk_false; | |
18012 | |
18013 { | |
18014 /* vertical scrollbar */ | |
18015 nk_flags state = 0; | |
18016 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; | |
18017 scroll.y = layout->bounds.y; | |
18018 scroll.w = scrollbar_size.x; | |
18019 scroll.h = layout->bounds.h; | |
18020 | |
18021 scroll_offset = (float)*layout->offset_y; | |
18022 scroll_step = scroll.h * 0.10f; | |
18023 scroll_inc = scroll.h * 0.01f; | |
18024 scroll_target = (float)(int)(layout->at_y - scroll.y); | |
18025 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, | |
18026 scroll_offset, scroll_target, scroll_step, scroll_inc, | |
18027 &ctx->style.scrollv, in, style->font); | |
18028 *layout->offset_y = (nk_uint)scroll_offset; | |
18029 if (in && scroll_has_scrolling) | |
18030 in->mouse.scroll_delta.y = 0; | |
18031 } | |
18032 { | |
18033 /* horizontal scrollbar */ | |
18034 nk_flags state = 0; | |
18035 scroll.x = layout->bounds.x; | |
18036 scroll.y = layout->bounds.y + layout->bounds.h; | |
18037 scroll.w = layout->bounds.w; | |
18038 scroll.h = scrollbar_size.y; | |
18039 | |
18040 scroll_offset = (float)*layout->offset_x; | |
18041 scroll_target = (float)(int)(layout->max_x - scroll.x); | |
18042 scroll_step = layout->max_x * 0.05f; | |
18043 scroll_inc = layout->max_x * 0.005f; | |
18044 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, | |
18045 scroll_offset, scroll_target, scroll_step, scroll_inc, | |
18046 &ctx->style.scrollh, in, style->font); | |
18047 *layout->offset_x = (nk_uint)scroll_offset; | |
18048 } | |
18049 } | |
18050 | |
18051 /* hide scroll if no user input */ | |
18052 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { | |
18053 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0; | |
18054 int is_window_hovered = nk_window_is_hovered(ctx); | |
18055 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); | |
18056 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) | |
18057 window->scrollbar_hiding_timer += ctx->delta_time_seconds; | |
18058 else window->scrollbar_hiding_timer = 0; | |
18059 } else window->scrollbar_hiding_timer = 0; | |
18060 | |
18061 /* window border */ | |
18062 if (layout->flags & NK_WINDOW_BORDER) | |
18063 { | |
18064 struct nk_color border_color = nk_panel_get_border_color(style, layout->type); | |
18065 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ? | |
18066 style->window.border + window->bounds.y + layout->header_height: | |
18067 (layout->flags & NK_WINDOW_DYNAMIC)? | |
18068 layout->bounds.y + layout->bounds.h + layout->footer_height: | |
18069 window->bounds.y + window->bounds.h; | |
18070 | |
18071 /* draw border top */ | |
18072 nk_stroke_line(out,window->bounds.x,window->bounds.y, | |
18073 window->bounds.x + window->bounds.w, window->bounds.y, | |
18074 layout->border, border_color); | |
18075 | |
18076 /* draw bottom border */ | |
18077 nk_stroke_line(out, window->bounds.x, padding_y, | |
18078 window->bounds.x + window->bounds.w, padding_y, layout->border, border_color); | |
18079 | |
18080 /* draw left border */ | |
18081 nk_stroke_line(out, window->bounds.x + layout->border*0.5f, | |
18082 window->bounds.y, window->bounds.x + layout->border*0.5f, | |
18083 padding_y, layout->border, border_color); | |
18084 | |
18085 /* draw right border */ | |
18086 nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f, | |
18087 window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f, | |
18088 padding_y, layout->border, border_color); | |
18089 } | |
18090 | |
18091 /* scaler */ | |
18092 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) | |
18093 { | |
18094 /* calculate scaler bounds */ | |
18095 struct nk_rect scaler; | |
18096 scaler.w = scrollbar_size.x; | |
18097 scaler.h = scrollbar_size.y; | |
18098 scaler.y = layout->bounds.y + layout->bounds.h; | |
18099 if (layout->flags & NK_WINDOW_SCALE_LEFT) | |
18100 scaler.x = layout->bounds.x - panel_padding.x * 0.5f; | |
18101 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; | |
18102 if (layout->flags & NK_WINDOW_NO_SCROLLBAR) | |
18103 scaler.x -= scaler.w; | |
18104 | |
18105 /* draw scaler */ | |
18106 {const struct nk_style_item *item = &style->window.scaler; | |
18107 if (item->type == NK_STYLE_ITEM_IMAGE) | |
18108 nk_draw_image(out, scaler, &item->data.image, nk_white); | |
18109 else { | |
18110 if (layout->flags & NK_WINDOW_SCALE_LEFT) { | |
18111 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x, | |
18112 scaler.y + scaler.h, scaler.x + scaler.w, | |
18113 scaler.y + scaler.h, item->data.color); | |
18114 } else { | |
18115 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, | |
18116 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); | |
18117 } | |
18118 }} | |
18119 | |
18120 /* do window scaling */ | |
18121 if (!(window->flags & NK_WINDOW_ROM)) { | |
18122 struct nk_vec2 window_size = style->window.min_size; | |
18123 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; | |
18124 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, | |
18125 NK_BUTTON_LEFT, scaler, nk_true); | |
18126 | |
18127 if (left_mouse_down && left_mouse_click_in_scaler) { | |
18128 float delta_x = in->mouse.delta.x; | |
18129 if (layout->flags & NK_WINDOW_SCALE_LEFT) { | |
18130 delta_x = -delta_x; | |
18131 window->bounds.x += in->mouse.delta.x; | |
18132 } | |
18133 /* dragging in x-direction */ | |
18134 if (window->bounds.w + delta_x >= window_size.x) { | |
18135 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) { | |
18136 window->bounds.w = window->bounds.w + delta_x; | |
18137 scaler.x += in->mouse.delta.x; | |
18138 } | |
18139 } | |
18140 /* dragging in y-direction (only possible if static window) */ | |
18141 if (!(layout->flags & NK_WINDOW_DYNAMIC)) { | |
18142 if (window_size.y < window->bounds.h + in->mouse.delta.y) { | |
18143 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) { | |
18144 window->bounds.h = window->bounds.h + in->mouse.delta.y; | |
18145 scaler.y += in->mouse.delta.y; | |
18146 } | |
18147 } | |
18148 } | |
18149 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; | |
18150 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f; | |
18151 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f; | |
18152 } | |
18153 } | |
18154 } | |
18155 if (!nk_panel_is_sub(layout->type)) { | |
18156 /* window is hidden so clear command buffer */ | |
18157 if (layout->flags & NK_WINDOW_HIDDEN) | |
18158 nk_command_buffer_reset(&window->buffer); | |
18159 /* window is visible and not tab */ | |
18160 else nk_finish(ctx, window); | |
18161 } | |
18162 | |
18163 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ | |
18164 if (layout->flags & NK_WINDOW_REMOVE_ROM) { | |
18165 layout->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18166 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; | |
18167 } | |
18168 window->flags = layout->flags; | |
18169 | |
18170 /* property garbage collector */ | |
18171 if (window->property.active && window->property.old != window->property.seq && | |
18172 window->property.active == window->property.prev) { | |
18173 nk_zero(&window->property, sizeof(window->property)); | |
18174 } else { | |
18175 window->property.old = window->property.seq; | |
18176 window->property.prev = window->property.active; | |
18177 window->property.seq = 0; | |
18178 } | |
18179 /* edit garbage collector */ | |
18180 if (window->edit.active && window->edit.old != window->edit.seq && | |
18181 window->edit.active == window->edit.prev) { | |
18182 nk_zero(&window->edit, sizeof(window->edit)); | |
18183 } else { | |
18184 window->edit.old = window->edit.seq; | |
18185 window->edit.prev = window->edit.active; | |
18186 window->edit.seq = 0; | |
18187 } | |
18188 /* contextual garbage collector */ | |
18189 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { | |
18190 window->popup.con_count = 0; | |
18191 window->popup.con_old = 0; | |
18192 window->popup.active_con = 0; | |
18193 } else { | |
18194 window->popup.con_old = window->popup.con_count; | |
18195 window->popup.con_count = 0; | |
18196 } | |
18197 window->popup.combo_count = 0; | |
18198 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */ | |
18199 NK_ASSERT(!layout->row.tree_depth); | |
18200 } | |
18201 | |
18202 /* ---------------------------------------------------------------- | |
18203 * | |
18204 * PAGE ELEMENT | |
18205 * | |
18206 * ---------------------------------------------------------------*/ | |
18207 NK_INTERN struct nk_page_element* | |
18208 nk_create_page_element(struct nk_context *ctx) | |
18209 { | |
18210 struct nk_page_element *elem; | |
18211 if (ctx->freelist) { | |
18212 /* unlink page element from free list */ | |
18213 elem = ctx->freelist; | |
18214 ctx->freelist = elem->next; | |
18215 } else if (ctx->use_pool) { | |
18216 /* allocate page element from memory pool */ | |
18217 elem = nk_pool_alloc(&ctx->pool); | |
18218 NK_ASSERT(elem); | |
18219 if (!elem) return 0; | |
18220 } else { | |
18221 /* allocate new page element from back of fixed size memory buffer */ | |
18222 NK_STORAGE const nk_size size = sizeof(struct nk_page_element); | |
18223 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); | |
18224 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); | |
18225 NK_ASSERT(elem); | |
18226 if (!elem) return 0; | |
18227 } | |
18228 nk_zero_struct(*elem); | |
18229 elem->next = 0; | |
18230 elem->prev = 0; | |
18231 return elem; | |
18232 } | |
18233 | |
18234 NK_INTERN void | |
18235 nk_link_page_element_into_freelist(struct nk_context *ctx, | |
18236 struct nk_page_element *elem) | |
18237 { | |
18238 /* link table into freelist */ | |
18239 if (!ctx->freelist) { | |
18240 ctx->freelist = elem; | |
18241 } else { | |
18242 elem->next = ctx->freelist; | |
18243 ctx->freelist = elem; | |
18244 } | |
18245 } | |
18246 | |
18247 NK_INTERN void | |
18248 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) | |
18249 { | |
18250 /* we have a pool so just add to free list */ | |
18251 if (ctx->use_pool) { | |
18252 nk_link_page_element_into_freelist(ctx, elem); | |
18253 return; | |
18254 } | |
18255 /* if possible remove last element from back of fixed memory buffer */ | |
18256 {void *elem_end = (void*)(elem + 1); | |
18257 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; | |
18258 if (elem_end == buffer_end) | |
18259 ctx->memory.size -= sizeof(struct nk_page_element); | |
18260 else nk_link_page_element_into_freelist(ctx, elem);} | |
18261 } | |
18262 | |
18263 /* ---------------------------------------------------------------- | |
18264 * | |
18265 * PANEL | |
18266 * | |
18267 * ---------------------------------------------------------------*/ | |
18268 NK_INTERN void* | |
18269 nk_create_panel(struct nk_context *ctx) | |
18270 { | |
18271 struct nk_page_element *elem; | |
18272 elem = nk_create_page_element(ctx); | |
18273 if (!elem) return 0; | |
18274 nk_zero_struct(*elem); | |
18275 return &elem->data.pan; | |
18276 } | |
18277 | |
18278 NK_INTERN void | |
18279 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) | |
18280 { | |
18281 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); | |
18282 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); | |
18283 nk_free_page_element(ctx, pe); | |
18284 } | |
18285 | |
18286 /* ---------------------------------------------------------------- | |
18287 * | |
18288 * TABLES | |
18289 * | |
18290 * ---------------------------------------------------------------*/ | |
18291 NK_INTERN struct nk_table* | |
18292 nk_create_table(struct nk_context *ctx) | |
18293 { | |
18294 struct nk_page_element *elem; | |
18295 elem = nk_create_page_element(ctx); | |
18296 if (!elem) return 0; | |
18297 nk_zero_struct(*elem); | |
18298 return &elem->data.tbl; | |
18299 } | |
18300 | |
18301 NK_INTERN void | |
18302 nk_free_table(struct nk_context *ctx, struct nk_table *tbl) | |
18303 { | |
18304 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); | |
18305 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); | |
18306 nk_free_page_element(ctx, pe); | |
18307 } | |
18308 | |
18309 NK_INTERN void | |
18310 nk_push_table(struct nk_window *win, struct nk_table *tbl) | |
18311 { | |
18312 if (!win->tables) { | |
18313 win->tables = tbl; | |
18314 tbl->next = 0; | |
18315 tbl->prev = 0; | |
18316 tbl->size = 0; | |
18317 win->table_count = 1; | |
18318 return; | |
18319 } | |
18320 win->tables->prev = tbl; | |
18321 tbl->next = win->tables; | |
18322 tbl->prev = 0; | |
18323 tbl->size = 0; | |
18324 win->tables = tbl; | |
18325 win->table_count++; | |
18326 } | |
18327 | |
18328 NK_INTERN void | |
18329 nk_remove_table(struct nk_window *win, struct nk_table *tbl) | |
18330 { | |
18331 if (win->tables == tbl) | |
18332 win->tables = tbl->next; | |
18333 if (tbl->next) | |
18334 tbl->next->prev = tbl->prev; | |
18335 if (tbl->prev) | |
18336 tbl->prev->next = tbl->next; | |
18337 tbl->next = 0; | |
18338 tbl->prev = 0; | |
18339 } | |
18340 | |
18341 NK_INTERN nk_uint* | |
18342 nk_add_value(struct nk_context *ctx, struct nk_window *win, | |
18343 nk_hash name, nk_uint value) | |
18344 { | |
18345 NK_ASSERT(ctx); | |
18346 NK_ASSERT(win); | |
18347 if (!win || !ctx) return 0; | |
18348 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) { | |
18349 struct nk_table *tbl = nk_create_table(ctx); | |
18350 NK_ASSERT(tbl); | |
18351 if (!tbl) return 0; | |
18352 nk_push_table(win, tbl); | |
18353 } | |
18354 win->tables->seq = win->seq; | |
18355 win->tables->keys[win->tables->size] = name; | |
18356 win->tables->values[win->tables->size] = value; | |
18357 return &win->tables->values[win->tables->size++]; | |
18358 } | |
18359 | |
18360 NK_INTERN nk_uint* | |
18361 nk_find_value(struct nk_window *win, nk_hash name) | |
18362 { | |
18363 struct nk_table *iter = win->tables; | |
18364 while (iter) { | |
18365 unsigned int i = 0; | |
18366 unsigned int size = iter->size; | |
18367 for (i = 0; i < size; ++i) { | |
18368 if (iter->keys[i] == name) { | |
18369 iter->seq = win->seq; | |
18370 return &iter->values[i]; | |
18371 } | |
18372 } size = NK_VALUE_PAGE_CAPACITY; | |
18373 iter = iter->next; | |
18374 } | |
18375 return 0; | |
18376 } | |
18377 | |
18378 /* ---------------------------------------------------------------- | |
18379 * | |
18380 * WINDOW | |
18381 * | |
18382 * ---------------------------------------------------------------*/ | |
18383 NK_INTERN void* | |
18384 nk_create_window(struct nk_context *ctx) | |
18385 { | |
18386 struct nk_page_element *elem; | |
18387 elem = nk_create_page_element(ctx); | |
18388 if (!elem) return 0; | |
18389 elem->data.win.seq = ctx->seq; | |
18390 return &elem->data.win; | |
18391 } | |
18392 | |
18393 NK_INTERN void | |
18394 nk_free_window(struct nk_context *ctx, struct nk_window *win) | |
18395 { | |
18396 /* unlink windows from list */ | |
18397 struct nk_table *it = win->tables; | |
18398 if (win->popup.win) { | |
18399 nk_free_window(ctx, win->popup.win); | |
18400 win->popup.win = 0; | |
18401 } | |
18402 win->next = 0; | |
18403 win->prev = 0; | |
18404 | |
18405 while (it) { | |
18406 /*free window state tables */ | |
18407 struct nk_table *n = it->next; | |
18408 nk_remove_table(win, it); | |
18409 nk_free_table(ctx, it); | |
18410 if (it == win->tables) | |
18411 win->tables = n; | |
18412 it = n; | |
18413 } | |
18414 | |
18415 /* link windows into freelist */ | |
18416 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); | |
18417 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); | |
18418 nk_free_page_element(ctx, pe);} | |
18419 } | |
18420 | |
18421 NK_INTERN struct nk_window* | |
18422 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) | |
18423 { | |
18424 struct nk_window *iter; | |
18425 iter = ctx->begin; | |
18426 while (iter) { | |
18427 NK_ASSERT(iter != iter->next); | |
18428 if (iter->name == hash) { | |
18429 int max_len = nk_strlen(iter->name_string); | |
18430 if (!nk_stricmpn(iter->name_string, name, max_len)) | |
18431 return iter; | |
18432 } | |
18433 iter = iter->next; | |
18434 } | |
18435 return 0; | |
18436 } | |
18437 | |
18438 enum nk_window_insert_location { | |
18439 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ | |
18440 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ | |
18441 }; | |
18442 NK_INTERN void | |
18443 nk_insert_window(struct nk_context *ctx, struct nk_window *win, | |
18444 enum nk_window_insert_location loc) | |
18445 { | |
18446 const struct nk_window *iter; | |
18447 NK_ASSERT(ctx); | |
18448 NK_ASSERT(win); | |
18449 if (!win || !ctx) return; | |
18450 | |
18451 iter = ctx->begin; | |
18452 while (iter) { | |
18453 NK_ASSERT(iter != iter->next); | |
18454 NK_ASSERT(iter != win); | |
18455 if (iter == win) return; | |
18456 iter = iter->next; | |
18457 } | |
18458 | |
18459 if (!ctx->begin) { | |
18460 win->next = 0; | |
18461 win->prev = 0; | |
18462 ctx->begin = win; | |
18463 ctx->end = win; | |
18464 ctx->count = 1; | |
18465 return; | |
18466 } | |
18467 if (loc == NK_INSERT_BACK) { | |
18468 struct nk_window *end; | |
18469 end = ctx->end; | |
18470 end->flags |= NK_WINDOW_ROM; | |
18471 end->next = win; | |
18472 win->prev = ctx->end; | |
18473 win->next = 0; | |
18474 ctx->end = win; | |
18475 ctx->active = ctx->end; | |
18476 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18477 } else { | |
18478 /*ctx->end->flags |= NK_WINDOW_ROM;*/ | |
18479 ctx->begin->prev = win; | |
18480 win->next = ctx->begin; | |
18481 win->prev = 0; | |
18482 ctx->begin = win; | |
18483 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18484 } | |
18485 ctx->count++; | |
18486 } | |
18487 | |
18488 NK_INTERN void | |
18489 nk_remove_window(struct nk_context *ctx, struct nk_window *win) | |
18490 { | |
18491 if (win == ctx->begin || win == ctx->end) { | |
18492 if (win == ctx->begin) { | |
18493 ctx->begin = win->next; | |
18494 if (win->next) | |
18495 win->next->prev = 0; | |
18496 } | |
18497 if (win == ctx->end) { | |
18498 ctx->end = win->prev; | |
18499 if (win->prev) | |
18500 win->prev->next = 0; | |
18501 } | |
18502 } else { | |
18503 if (win->next) | |
18504 win->next->prev = win->prev; | |
18505 if (win->prev) | |
18506 win->prev->next = win->next; | |
18507 } | |
18508 if (win == ctx->active || !ctx->active) { | |
18509 ctx->active = ctx->end; | |
18510 if (ctx->end) | |
18511 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18512 } | |
18513 win->next = 0; | |
18514 win->prev = 0; | |
18515 ctx->count--; | |
18516 } | |
18517 | |
18518 NK_API int | |
18519 nk_begin(struct nk_context *ctx, const char *title, | |
18520 struct nk_rect bounds, nk_flags flags) | |
18521 { | |
18522 return nk_begin_titled(ctx, title, title, bounds, flags); | |
18523 } | |
18524 | |
18525 NK_API int | |
18526 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, | |
18527 struct nk_rect bounds, nk_flags flags) | |
18528 { | |
18529 struct nk_window *win; | |
18530 struct nk_style *style; | |
18531 nk_hash title_hash; | |
18532 int title_len; | |
18533 int ret = 0; | |
18534 | |
18535 NK_ASSERT(ctx); | |
18536 NK_ASSERT(name); | |
18537 NK_ASSERT(title); | |
18538 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); | |
18539 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); | |
18540 if (!ctx || ctx->current || !title || !name) | |
18541 return 0; | |
18542 | |
18543 /* find or create window */ | |
18544 style = &ctx->style; | |
18545 title_len = (int)nk_strlen(name); | |
18546 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18547 win = nk_find_window(ctx, title_hash, name); | |
18548 if (!win) { | |
18549 /* create new window */ | |
18550 nk_size name_length = (nk_size)nk_strlen(name); | |
18551 win = (struct nk_window*)nk_create_window(ctx); | |
18552 NK_ASSERT(win); | |
18553 if (!win) return 0; | |
18554 | |
18555 if (flags & NK_WINDOW_BACKGROUND) | |
18556 nk_insert_window(ctx, win, NK_INSERT_FRONT); | |
18557 else nk_insert_window(ctx, win, NK_INSERT_BACK); | |
18558 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); | |
18559 | |
18560 win->flags = flags; | |
18561 win->bounds = bounds; | |
18562 win->name = title_hash; | |
18563 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); | |
18564 NK_MEMCPY(win->name_string, name, name_length); | |
18565 win->name_string[name_length] = 0; | |
18566 win->popup.win = 0; | |
18567 if (!ctx->active) | |
18568 ctx->active = win; | |
18569 } else { | |
18570 /* update window */ | |
18571 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); | |
18572 win->flags |= flags; | |
18573 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) | |
18574 win->bounds = bounds; | |
18575 /* If this assert triggers you either: | |
18576 * | |
18577 * I.) Have more than one window with the same name or | |
18578 * II.) You forgot to actually draw the window. | |
18579 * More specific you did not call `nk_clear` (nk_clear will be | |
18580 * automatically called for you if you are using one of the | |
18581 * provided demo backends). */ | |
18582 NK_ASSERT(win->seq != ctx->seq); | |
18583 win->seq = ctx->seq; | |
18584 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) { | |
18585 ctx->active = win; | |
18586 ctx->end = win; | |
18587 } | |
18588 } | |
18589 if (win->flags & NK_WINDOW_HIDDEN) { | |
18590 ctx->current = win; | |
18591 win->layout = 0; | |
18592 return 0; | |
18593 } | |
18594 | |
18595 /* window overlapping */ | |
18596 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT)) | |
18597 { | |
18598 int inpanel, ishovered; | |
18599 struct nk_window *iter = win; | |
18600 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + | |
18601 (2.0f * style->window.header.label_padding.y); | |
18602 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? | |
18603 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); | |
18604 | |
18605 /* activate window if hovered and no other window is overlapping this window */ | |
18606 nk_start(ctx, win); | |
18607 inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); | |
18608 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; | |
18609 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); | |
18610 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { | |
18611 iter = win->next; | |
18612 while (iter) { | |
18613 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? | |
18614 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); | |
18615 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, | |
18616 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && | |
18617 (!(iter->flags & NK_WINDOW_HIDDEN))) | |
18618 break; | |
18619 | |
18620 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && | |
18621 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, | |
18622 iter->popup.win->bounds.x, iter->popup.win->bounds.y, | |
18623 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) | |
18624 break; | |
18625 iter = iter->next; | |
18626 } | |
18627 } | |
18628 | |
18629 /* activate window if clicked */ | |
18630 if (iter && inpanel && (win != ctx->end)) { | |
18631 iter = win->next; | |
18632 while (iter) { | |
18633 /* try to find a panel with higher priority in the same position */ | |
18634 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? | |
18635 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); | |
18636 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, | |
18637 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && | |
18638 !(iter->flags & NK_WINDOW_HIDDEN)) | |
18639 break; | |
18640 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && | |
18641 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, | |
18642 iter->popup.win->bounds.x, iter->popup.win->bounds.y, | |
18643 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) | |
18644 break; | |
18645 iter = iter->next; | |
18646 } | |
18647 } | |
18648 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) { | |
18649 win->flags |= (nk_flags)NK_WINDOW_ROM; | |
18650 iter->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18651 ctx->active = iter; | |
18652 if (!(iter->flags & NK_WINDOW_BACKGROUND)) { | |
18653 /* current window is active in that position so transfer to top | |
18654 * at the highest priority in stack */ | |
18655 nk_remove_window(ctx, iter); | |
18656 nk_insert_window(ctx, iter, NK_INSERT_BACK); | |
18657 } | |
18658 } else { | |
18659 if (!iter && ctx->end != win) { | |
18660 if (!(win->flags & NK_WINDOW_BACKGROUND)) { | |
18661 /* current window is active in that position so transfer to top | |
18662 * at the highest priority in stack */ | |
18663 nk_remove_window(ctx, win); | |
18664 nk_insert_window(ctx, win, NK_INSERT_BACK); | |
18665 } | |
18666 win->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
18667 ctx->active = win; | |
18668 } | |
18669 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) | |
18670 win->flags |= NK_WINDOW_ROM; | |
18671 } | |
18672 } | |
18673 | |
18674 win->layout = (struct nk_panel*)nk_create_panel(ctx); | |
18675 ctx->current = win; | |
18676 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); | |
18677 win->layout->offset_x = &win->scrollbar.x; | |
18678 win->layout->offset_y = &win->scrollbar.y; | |
18679 return ret; | |
18680 } | |
18681 | |
18682 NK_API void | |
18683 nk_end(struct nk_context *ctx) | |
18684 { | |
18685 struct nk_panel *layout; | |
18686 NK_ASSERT(ctx); | |
18687 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); | |
18688 if (!ctx || !ctx->current) | |
18689 return; | |
18690 | |
18691 layout = ctx->current->layout; | |
18692 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) { | |
18693 ctx->current = 0; | |
18694 return; | |
18695 } | |
18696 nk_panel_end(ctx); | |
18697 nk_free_panel(ctx, ctx->current->layout); | |
18698 ctx->current = 0; | |
18699 } | |
18700 | |
18701 NK_API struct nk_rect | |
18702 nk_window_get_bounds(const struct nk_context *ctx) | |
18703 { | |
18704 NK_ASSERT(ctx); | |
18705 NK_ASSERT(ctx->current); | |
18706 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); | |
18707 return ctx->current->bounds; | |
18708 } | |
18709 | |
18710 NK_API struct nk_vec2 | |
18711 nk_window_get_position(const struct nk_context *ctx) | |
18712 { | |
18713 NK_ASSERT(ctx); | |
18714 NK_ASSERT(ctx->current); | |
18715 if (!ctx || !ctx->current) return nk_vec2(0,0); | |
18716 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); | |
18717 } | |
18718 | |
18719 NK_API struct nk_vec2 | |
18720 nk_window_get_size(const struct nk_context *ctx) | |
18721 { | |
18722 NK_ASSERT(ctx); | |
18723 NK_ASSERT(ctx->current); | |
18724 if (!ctx || !ctx->current) return nk_vec2(0,0); | |
18725 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); | |
18726 } | |
18727 | |
18728 NK_API float | |
18729 nk_window_get_width(const struct nk_context *ctx) | |
18730 { | |
18731 NK_ASSERT(ctx); | |
18732 NK_ASSERT(ctx->current); | |
18733 if (!ctx || !ctx->current) return 0; | |
18734 return ctx->current->bounds.w; | |
18735 } | |
18736 | |
18737 NK_API float | |
18738 nk_window_get_height(const struct nk_context *ctx) | |
18739 { | |
18740 NK_ASSERT(ctx); | |
18741 NK_ASSERT(ctx->current); | |
18742 if (!ctx || !ctx->current) return 0; | |
18743 return ctx->current->bounds.h; | |
18744 } | |
18745 | |
18746 NK_API struct nk_rect | |
18747 nk_window_get_content_region(struct nk_context *ctx) | |
18748 { | |
18749 NK_ASSERT(ctx); | |
18750 NK_ASSERT(ctx->current); | |
18751 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); | |
18752 return ctx->current->layout->clip; | |
18753 } | |
18754 | |
18755 NK_API struct nk_vec2 | |
18756 nk_window_get_content_region_min(struct nk_context *ctx) | |
18757 { | |
18758 NK_ASSERT(ctx); | |
18759 NK_ASSERT(ctx->current); | |
18760 NK_ASSERT(ctx->current->layout); | |
18761 if (!ctx || !ctx->current) return nk_vec2(0,0); | |
18762 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); | |
18763 } | |
18764 | |
18765 NK_API struct nk_vec2 | |
18766 nk_window_get_content_region_max(struct nk_context *ctx) | |
18767 { | |
18768 NK_ASSERT(ctx); | |
18769 NK_ASSERT(ctx->current); | |
18770 NK_ASSERT(ctx->current->layout); | |
18771 if (!ctx || !ctx->current) return nk_vec2(0,0); | |
18772 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, | |
18773 ctx->current->layout->clip.y + ctx->current->layout->clip.h); | |
18774 } | |
18775 | |
18776 NK_API struct nk_vec2 | |
18777 nk_window_get_content_region_size(struct nk_context *ctx) | |
18778 { | |
18779 NK_ASSERT(ctx); | |
18780 NK_ASSERT(ctx->current); | |
18781 NK_ASSERT(ctx->current->layout); | |
18782 if (!ctx || !ctx->current) return nk_vec2(0,0); | |
18783 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); | |
18784 } | |
18785 | |
18786 NK_API struct nk_command_buffer* | |
18787 nk_window_get_canvas(struct nk_context *ctx) | |
18788 { | |
18789 NK_ASSERT(ctx); | |
18790 NK_ASSERT(ctx->current); | |
18791 NK_ASSERT(ctx->current->layout); | |
18792 if (!ctx || !ctx->current) return 0; | |
18793 return &ctx->current->buffer; | |
18794 } | |
18795 | |
18796 NK_API struct nk_panel* | |
18797 nk_window_get_panel(struct nk_context *ctx) | |
18798 { | |
18799 NK_ASSERT(ctx); | |
18800 NK_ASSERT(ctx->current); | |
18801 if (!ctx || !ctx->current) return 0; | |
18802 return ctx->current->layout; | |
18803 } | |
18804 | |
18805 NK_API int | |
18806 nk_window_has_focus(const struct nk_context *ctx) | |
18807 { | |
18808 NK_ASSERT(ctx); | |
18809 NK_ASSERT(ctx->current); | |
18810 NK_ASSERT(ctx->current->layout); | |
18811 if (!ctx || !ctx->current) return 0; | |
18812 return ctx->current == ctx->active; | |
18813 } | |
18814 | |
18815 NK_API int | |
18816 nk_window_is_hovered(struct nk_context *ctx) | |
18817 { | |
18818 NK_ASSERT(ctx); | |
18819 NK_ASSERT(ctx->current); | |
18820 if (!ctx || !ctx->current) return 0; | |
18821 if(ctx->current->flags & NK_WINDOW_HIDDEN) | |
18822 return 0; | |
18823 return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds); | |
18824 } | |
18825 | |
18826 NK_API int | |
18827 nk_window_is_any_hovered(struct nk_context *ctx) | |
18828 { | |
18829 struct nk_window *iter; | |
18830 NK_ASSERT(ctx); | |
18831 if (!ctx) return 0; | |
18832 iter = ctx->begin; | |
18833 while (iter) { | |
18834 /* check if window is being hovered */ | |
18835 if(!(iter->flags & NK_WINDOW_HIDDEN)) { | |
18836 /* check if window popup is being hovered */ | |
18837 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) | |
18838 return 1; | |
18839 | |
18840 if (iter->flags & NK_WINDOW_MINIMIZED) { | |
18841 struct nk_rect header = iter->bounds; | |
18842 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; | |
18843 if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) | |
18844 return 1; | |
18845 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { | |
18846 return 1; | |
18847 } | |
18848 } | |
18849 iter = iter->next; | |
18850 } | |
18851 return 0; | |
18852 } | |
18853 | |
18854 NK_API int | |
18855 nk_item_is_any_active(struct nk_context *ctx) | |
18856 { | |
18857 int any_hovered = nk_window_is_any_hovered(ctx); | |
18858 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); | |
18859 return any_hovered || any_active; | |
18860 } | |
18861 | |
18862 NK_API int | |
18863 nk_window_is_collapsed(struct nk_context *ctx, const char *name) | |
18864 { | |
18865 int title_len; | |
18866 nk_hash title_hash; | |
18867 struct nk_window *win; | |
18868 NK_ASSERT(ctx); | |
18869 if (!ctx) return 0; | |
18870 | |
18871 title_len = (int)nk_strlen(name); | |
18872 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18873 win = nk_find_window(ctx, title_hash, name); | |
18874 if (!win) return 0; | |
18875 return win->flags & NK_WINDOW_MINIMIZED; | |
18876 } | |
18877 | |
18878 NK_API int | |
18879 nk_window_is_closed(struct nk_context *ctx, const char *name) | |
18880 { | |
18881 int title_len; | |
18882 nk_hash title_hash; | |
18883 struct nk_window *win; | |
18884 NK_ASSERT(ctx); | |
18885 if (!ctx) return 1; | |
18886 | |
18887 title_len = (int)nk_strlen(name); | |
18888 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18889 win = nk_find_window(ctx, title_hash, name); | |
18890 if (!win) return 1; | |
18891 return (win->flags & NK_WINDOW_CLOSED); | |
18892 } | |
18893 | |
18894 NK_API int | |
18895 nk_window_is_hidden(struct nk_context *ctx, const char *name) | |
18896 { | |
18897 int title_len; | |
18898 nk_hash title_hash; | |
18899 struct nk_window *win; | |
18900 NK_ASSERT(ctx); | |
18901 if (!ctx) return 1; | |
18902 | |
18903 title_len = (int)nk_strlen(name); | |
18904 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18905 win = nk_find_window(ctx, title_hash, name); | |
18906 if (!win) return 1; | |
18907 return (win->flags & NK_WINDOW_HIDDEN); | |
18908 } | |
18909 | |
18910 NK_API int | |
18911 nk_window_is_active(struct nk_context *ctx, const char *name) | |
18912 { | |
18913 int title_len; | |
18914 nk_hash title_hash; | |
18915 struct nk_window *win; | |
18916 NK_ASSERT(ctx); | |
18917 if (!ctx) return 0; | |
18918 | |
18919 title_len = (int)nk_strlen(name); | |
18920 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18921 win = nk_find_window(ctx, title_hash, name); | |
18922 if (!win) return 0; | |
18923 return win == ctx->active; | |
18924 } | |
18925 | |
18926 NK_API struct nk_window* | |
18927 nk_window_find(struct nk_context *ctx, const char *name) | |
18928 { | |
18929 int title_len; | |
18930 nk_hash title_hash; | |
18931 title_len = (int)nk_strlen(name); | |
18932 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18933 return nk_find_window(ctx, title_hash, name); | |
18934 } | |
18935 | |
18936 NK_API void | |
18937 nk_window_close(struct nk_context *ctx, const char *name) | |
18938 { | |
18939 struct nk_window *win; | |
18940 NK_ASSERT(ctx); | |
18941 if (!ctx) return; | |
18942 win = nk_window_find(ctx, name); | |
18943 if (!win) return; | |
18944 NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); | |
18945 if (ctx->current == win) return; | |
18946 win->flags |= NK_WINDOW_HIDDEN; | |
18947 win->flags |= NK_WINDOW_CLOSED; | |
18948 } | |
18949 | |
18950 NK_API void | |
18951 nk_window_set_bounds(struct nk_context *ctx, | |
18952 const char *name, struct nk_rect bounds) | |
18953 { | |
18954 struct nk_window *win; | |
18955 NK_ASSERT(ctx); | |
18956 if (!ctx) return; | |
18957 win = nk_window_find(ctx, name); | |
18958 if (!win) return; | |
18959 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window"); | |
18960 win->bounds = bounds; | |
18961 } | |
18962 | |
18963 NK_API void | |
18964 nk_window_set_position(struct nk_context *ctx, | |
18965 const char *name, struct nk_vec2 pos) | |
18966 { | |
18967 struct nk_window *win = nk_window_find(ctx, name); | |
18968 if (!win) return; | |
18969 win->bounds.x = pos.x; | |
18970 win->bounds.y = pos.y; | |
18971 } | |
18972 | |
18973 NK_API void | |
18974 nk_window_set_size(struct nk_context *ctx, | |
18975 const char *name, struct nk_vec2 size) | |
18976 { | |
18977 struct nk_window *win = nk_window_find(ctx, name); | |
18978 if (!win) return; | |
18979 win->bounds.w = size.x; | |
18980 win->bounds.h = size.y; | |
18981 } | |
18982 | |
18983 NK_API void | |
18984 nk_window_collapse(struct nk_context *ctx, const char *name, | |
18985 enum nk_collapse_states c) | |
18986 { | |
18987 int title_len; | |
18988 nk_hash title_hash; | |
18989 struct nk_window *win; | |
18990 NK_ASSERT(ctx); | |
18991 if (!ctx) return; | |
18992 | |
18993 title_len = (int)nk_strlen(name); | |
18994 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
18995 win = nk_find_window(ctx, title_hash, name); | |
18996 if (!win) return; | |
18997 if (c == NK_MINIMIZED) | |
18998 win->flags |= NK_WINDOW_MINIMIZED; | |
18999 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; | |
19000 } | |
19001 | |
19002 NK_API void | |
19003 nk_window_collapse_if(struct nk_context *ctx, const char *name, | |
19004 enum nk_collapse_states c, int cond) | |
19005 { | |
19006 NK_ASSERT(ctx); | |
19007 if (!ctx || !cond) return; | |
19008 nk_window_collapse(ctx, name, c); | |
19009 } | |
19010 | |
19011 NK_API void | |
19012 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) | |
19013 { | |
19014 int title_len; | |
19015 nk_hash title_hash; | |
19016 struct nk_window *win; | |
19017 NK_ASSERT(ctx); | |
19018 if (!ctx) return; | |
19019 | |
19020 title_len = (int)nk_strlen(name); | |
19021 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
19022 win = nk_find_window(ctx, title_hash, name); | |
19023 if (!win) return; | |
19024 if (s == NK_HIDDEN) { | |
19025 win->flags |= NK_WINDOW_HIDDEN; | |
19026 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; | |
19027 } | |
19028 | |
19029 NK_API void | |
19030 nk_window_show_if(struct nk_context *ctx, const char *name, | |
19031 enum nk_show_states s, int cond) | |
19032 { | |
19033 NK_ASSERT(ctx); | |
19034 if (!ctx || !cond) return; | |
19035 nk_window_show(ctx, name, s); | |
19036 } | |
19037 | |
19038 NK_API void | |
19039 nk_window_set_focus(struct nk_context *ctx, const char *name) | |
19040 { | |
19041 int title_len; | |
19042 nk_hash title_hash; | |
19043 struct nk_window *win; | |
19044 NK_ASSERT(ctx); | |
19045 if (!ctx) return; | |
19046 | |
19047 title_len = (int)nk_strlen(name); | |
19048 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); | |
19049 win = nk_find_window(ctx, title_hash, name); | |
19050 if (win && ctx->end != win) { | |
19051 nk_remove_window(ctx, win); | |
19052 nk_insert_window(ctx, win, NK_INSERT_BACK); | |
19053 } | |
19054 ctx->active = win; | |
19055 } | |
19056 | |
19057 /*---------------------------------------------------------------- | |
19058 * | |
19059 * MENUBAR | |
19060 * | |
19061 * --------------------------------------------------------------*/ | |
19062 NK_API void | |
19063 nk_menubar_begin(struct nk_context *ctx) | |
19064 { | |
19065 struct nk_panel *layout; | |
19066 NK_ASSERT(ctx); | |
19067 NK_ASSERT(ctx->current); | |
19068 NK_ASSERT(ctx->current->layout); | |
19069 if (!ctx || !ctx->current || !ctx->current->layout) | |
19070 return; | |
19071 | |
19072 layout = ctx->current->layout; | |
19073 NK_ASSERT(layout->at_y == layout->bounds.y); | |
19074 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. | |
19075 If you want a menubar the first nuklear function after `nk_begin` has to be a | |
19076 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for | |
19077 widgets (also supports multiple rows). | |
19078 Example: | |
19079 if (nk_begin(...)) { | |
19080 nk_menubar_begin(...); | |
19081 nk_layout_xxxx(...); | |
19082 nk_button(...); | |
19083 nk_layout_xxxx(...); | |
19084 nk_button(...); | |
19085 nk_menubar_end(...); | |
19086 } | |
19087 nk_end(...); | |
19088 */ | |
19089 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) | |
19090 return; | |
19091 | |
19092 layout->menu.x = layout->at_x; | |
19093 layout->menu.y = layout->at_y + layout->row.height; | |
19094 layout->menu.w = layout->bounds.w; | |
19095 layout->menu.offset.x = *layout->offset_x; | |
19096 layout->menu.offset.y = *layout->offset_y; | |
19097 *layout->offset_y = 0; | |
19098 } | |
19099 | |
19100 NK_API void | |
19101 nk_menubar_end(struct nk_context *ctx) | |
19102 { | |
19103 struct nk_window *win; | |
19104 struct nk_panel *layout; | |
19105 struct nk_command_buffer *out; | |
19106 | |
19107 NK_ASSERT(ctx); | |
19108 NK_ASSERT(ctx->current); | |
19109 NK_ASSERT(ctx->current->layout); | |
19110 if (!ctx || !ctx->current || !ctx->current->layout) | |
19111 return; | |
19112 | |
19113 win = ctx->current; | |
19114 out = &win->buffer; | |
19115 layout = win->layout; | |
19116 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) | |
19117 return; | |
19118 | |
19119 layout->menu.h = layout->at_y - layout->menu.y; | |
19120 layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height; | |
19121 layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height; | |
19122 | |
19123 *layout->offset_x = layout->menu.offset.x; | |
19124 *layout->offset_y = layout->menu.offset.y; | |
19125 layout->at_y = layout->bounds.y - layout->row.height; | |
19126 | |
19127 layout->clip.y = layout->bounds.y; | |
19128 layout->clip.h = layout->bounds.h; | |
19129 nk_push_scissor(out, layout->clip); | |
19130 } | |
19131 /* ------------------------------------------------------------- | |
19132 * | |
19133 * LAYOUT | |
19134 * | |
19135 * --------------------------------------------------------------*/ | |
19136 NK_API void | |
19137 nk_layout_set_min_row_height(struct nk_context *ctx, float height) | |
19138 { | |
19139 struct nk_window *win; | |
19140 struct nk_panel *layout; | |
19141 | |
19142 NK_ASSERT(ctx); | |
19143 NK_ASSERT(ctx->current); | |
19144 NK_ASSERT(ctx->current->layout); | |
19145 if (!ctx || !ctx->current || !ctx->current->layout) | |
19146 return; | |
19147 | |
19148 win = ctx->current; | |
19149 layout = win->layout; | |
19150 layout->row.min_height = height; | |
19151 } | |
19152 | |
19153 NK_API void | |
19154 nk_layout_reset_min_row_height(struct nk_context *ctx) | |
19155 { | |
19156 struct nk_window *win; | |
19157 struct nk_panel *layout; | |
19158 | |
19159 NK_ASSERT(ctx); | |
19160 NK_ASSERT(ctx->current); | |
19161 NK_ASSERT(ctx->current->layout); | |
19162 if (!ctx || !ctx->current || !ctx->current->layout) | |
19163 return; | |
19164 | |
19165 win = ctx->current; | |
19166 layout = win->layout; | |
19167 layout->row.min_height = ctx->style.font->height; | |
19168 layout->row.min_height += ctx->style.text.padding.y*2; | |
19169 layout->row.min_height += ctx->style.window.min_row_height_padding*2; | |
19170 } | |
19171 | |
19172 NK_INTERN float | |
19173 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, | |
19174 float total_space, int columns) | |
19175 { | |
19176 float panel_padding; | |
19177 float panel_spacing; | |
19178 float panel_space; | |
19179 | |
19180 struct nk_vec2 spacing; | |
19181 struct nk_vec2 padding; | |
19182 | |
19183 spacing = style->window.spacing; | |
19184 padding = nk_panel_get_padding(style, type); | |
19185 | |
19186 /* calculate the usable panel space */ | |
19187 panel_padding = 2 * padding.x; | |
19188 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x; | |
19189 panel_space = total_space - panel_padding - panel_spacing; | |
19190 return panel_space; | |
19191 } | |
19192 | |
19193 NK_INTERN void | |
19194 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, | |
19195 float height, int cols) | |
19196 { | |
19197 struct nk_panel *layout; | |
19198 const struct nk_style *style; | |
19199 struct nk_command_buffer *out; | |
19200 | |
19201 struct nk_vec2 item_spacing; | |
19202 struct nk_color color; | |
19203 | |
19204 NK_ASSERT(ctx); | |
19205 NK_ASSERT(ctx->current); | |
19206 NK_ASSERT(ctx->current->layout); | |
19207 if (!ctx || !ctx->current || !ctx->current->layout) | |
19208 return; | |
19209 | |
19210 /* prefetch some configuration data */ | |
19211 layout = win->layout; | |
19212 style = &ctx->style; | |
19213 out = &win->buffer; | |
19214 color = style->window.background; | |
19215 item_spacing = style->window.spacing; | |
19216 | |
19217 /* if one of these triggers you forgot to add an `if` condition around either | |
19218 a window, group, popup, combobox or contextual menu `begin` and `end` block. | |
19219 Example: | |
19220 if (nk_begin(...) {...} nk_end(...); or | |
19221 if (nk_group_begin(...) { nk_group_end(...);} */ | |
19222 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); | |
19223 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); | |
19224 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); | |
19225 | |
19226 /* update the current row and set the current row layout */ | |
19227 layout->row.index = 0; | |
19228 layout->at_y += layout->row.height; | |
19229 layout->row.columns = cols; | |
19230 if (height == 0.0f) | |
19231 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y; | |
19232 else layout->row.height = height + item_spacing.y; | |
19233 | |
19234 layout->row.item_offset = 0; | |
19235 if (layout->flags & NK_WINDOW_DYNAMIC) { | |
19236 /* draw background for dynamic panels */ | |
19237 struct nk_rect background; | |
19238 background.x = win->bounds.x; | |
19239 background.w = win->bounds.w; | |
19240 background.y = layout->at_y - 1.0f; | |
19241 background.h = layout->row.height + 1.0f; | |
19242 nk_fill_rect(out, background, 0, color); | |
19243 } | |
19244 } | |
19245 | |
19246 NK_INTERN void | |
19247 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, | |
19248 float height, int cols, int width) | |
19249 { | |
19250 /* update the current row and set the current row layout */ | |
19251 struct nk_window *win; | |
19252 NK_ASSERT(ctx); | |
19253 NK_ASSERT(ctx->current); | |
19254 NK_ASSERT(ctx->current->layout); | |
19255 if (!ctx || !ctx->current || !ctx->current->layout) | |
19256 return; | |
19257 | |
19258 win = ctx->current; | |
19259 nk_panel_layout(ctx, win, height, cols); | |
19260 if (fmt == NK_DYNAMIC) | |
19261 win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; | |
19262 else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; | |
19263 | |
19264 win->layout->row.ratio = 0; | |
19265 win->layout->row.filled = 0; | |
19266 win->layout->row.item_offset = 0; | |
19267 win->layout->row.item_width = (float)width; | |
19268 } | |
19269 | |
19270 NK_API float | |
19271 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) | |
19272 { | |
19273 struct nk_window *win; | |
19274 NK_ASSERT(ctx); | |
19275 NK_ASSERT(pixel_width); | |
19276 if (!ctx || !ctx->current || !ctx->current->layout) return 0; | |
19277 win = ctx->current; | |
19278 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); | |
19279 } | |
19280 | |
19281 NK_API void | |
19282 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) | |
19283 { | |
19284 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); | |
19285 } | |
19286 | |
19287 NK_API void | |
19288 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) | |
19289 { | |
19290 nk_row_layout(ctx, NK_STATIC, height, cols, item_width); | |
19291 } | |
19292 | |
19293 NK_API void | |
19294 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, | |
19295 float row_height, int cols) | |
19296 { | |
19297 struct nk_window *win; | |
19298 struct nk_panel *layout; | |
19299 | |
19300 NK_ASSERT(ctx); | |
19301 NK_ASSERT(ctx->current); | |
19302 NK_ASSERT(ctx->current->layout); | |
19303 if (!ctx || !ctx->current || !ctx->current->layout) | |
19304 return; | |
19305 | |
19306 win = ctx->current; | |
19307 layout = win->layout; | |
19308 nk_panel_layout(ctx, win, row_height, cols); | |
19309 if (fmt == NK_DYNAMIC) | |
19310 layout->row.type = NK_LAYOUT_DYNAMIC_ROW; | |
19311 else layout->row.type = NK_LAYOUT_STATIC_ROW; | |
19312 | |
19313 layout->row.ratio = 0; | |
19314 layout->row.filled = 0; | |
19315 layout->row.item_width = 0; | |
19316 layout->row.item_offset = 0; | |
19317 layout->row.columns = cols; | |
19318 } | |
19319 | |
19320 NK_API void | |
19321 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) | |
19322 { | |
19323 struct nk_window *win; | |
19324 struct nk_panel *layout; | |
19325 | |
19326 NK_ASSERT(ctx); | |
19327 NK_ASSERT(ctx->current); | |
19328 NK_ASSERT(ctx->current->layout); | |
19329 if (!ctx || !ctx->current || !ctx->current->layout) | |
19330 return; | |
19331 | |
19332 win = ctx->current; | |
19333 layout = win->layout; | |
19334 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); | |
19335 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) | |
19336 return; | |
19337 | |
19338 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { | |
19339 float ratio = ratio_or_width; | |
19340 if ((ratio + layout->row.filled) > 1.0f) return; | |
19341 if (ratio > 0.0f) | |
19342 layout->row.item_width = NK_SATURATE(ratio); | |
19343 else layout->row.item_width = 1.0f - layout->row.filled; | |
19344 } else layout->row.item_width = ratio_or_width; | |
19345 } | |
19346 | |
19347 NK_API void | |
19348 nk_layout_row_end(struct nk_context *ctx) | |
19349 { | |
19350 struct nk_window *win; | |
19351 struct nk_panel *layout; | |
19352 | |
19353 NK_ASSERT(ctx); | |
19354 NK_ASSERT(ctx->current); | |
19355 NK_ASSERT(ctx->current->layout); | |
19356 if (!ctx || !ctx->current || !ctx->current->layout) | |
19357 return; | |
19358 | |
19359 win = ctx->current; | |
19360 layout = win->layout; | |
19361 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); | |
19362 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) | |
19363 return; | |
19364 layout->row.item_width = 0; | |
19365 layout->row.item_offset = 0; | |
19366 } | |
19367 | |
19368 NK_API void | |
19369 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, | |
19370 float height, int cols, const float *ratio) | |
19371 { | |
19372 int i; | |
19373 int n_undef = 0; | |
19374 struct nk_window *win; | |
19375 struct nk_panel *layout; | |
19376 | |
19377 NK_ASSERT(ctx); | |
19378 NK_ASSERT(ctx->current); | |
19379 NK_ASSERT(ctx->current->layout); | |
19380 if (!ctx || !ctx->current || !ctx->current->layout) | |
19381 return; | |
19382 | |
19383 win = ctx->current; | |
19384 layout = win->layout; | |
19385 nk_panel_layout(ctx, win, height, cols); | |
19386 if (fmt == NK_DYNAMIC) { | |
19387 /* calculate width of undefined widget ratios */ | |
19388 float r = 0; | |
19389 layout->row.ratio = ratio; | |
19390 for (i = 0; i < cols; ++i) { | |
19391 if (ratio[i] < 0.0f) | |
19392 n_undef++; | |
19393 else r += ratio[i]; | |
19394 } | |
19395 r = NK_SATURATE(1.0f - r); | |
19396 layout->row.type = NK_LAYOUT_DYNAMIC; | |
19397 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; | |
19398 } else { | |
19399 layout->row.ratio = ratio; | |
19400 layout->row.type = NK_LAYOUT_STATIC; | |
19401 layout->row.item_width = 0; | |
19402 layout->row.item_offset = 0; | |
19403 } | |
19404 layout->row.item_offset = 0; | |
19405 layout->row.filled = 0; | |
19406 } | |
19407 | |
19408 NK_API void | |
19409 nk_layout_row_template_begin(struct nk_context *ctx, float height) | |
19410 { | |
19411 struct nk_window *win; | |
19412 struct nk_panel *layout; | |
19413 | |
19414 NK_ASSERT(ctx); | |
19415 NK_ASSERT(ctx->current); | |
19416 NK_ASSERT(ctx->current->layout); | |
19417 if (!ctx || !ctx->current || !ctx->current->layout) | |
19418 return; | |
19419 | |
19420 win = ctx->current; | |
19421 layout = win->layout; | |
19422 nk_panel_layout(ctx, win, height, 1); | |
19423 layout->row.type = NK_LAYOUT_TEMPLATE; | |
19424 layout->row.columns = 0; | |
19425 layout->row.ratio = 0; | |
19426 layout->row.item_width = 0; | |
19427 layout->row.item_height = 0; | |
19428 layout->row.item_offset = 0; | |
19429 layout->row.filled = 0; | |
19430 layout->row.item.x = 0; | |
19431 layout->row.item.y = 0; | |
19432 layout->row.item.w = 0; | |
19433 layout->row.item.h = 0; | |
19434 } | |
19435 | |
19436 NK_API void | |
19437 nk_layout_row_template_push_dynamic(struct nk_context *ctx) | |
19438 { | |
19439 struct nk_window *win; | |
19440 struct nk_panel *layout; | |
19441 | |
19442 NK_ASSERT(ctx); | |
19443 NK_ASSERT(ctx->current); | |
19444 NK_ASSERT(ctx->current->layout); | |
19445 if (!ctx || !ctx->current || !ctx->current->layout) | |
19446 return; | |
19447 | |
19448 win = ctx->current; | |
19449 layout = win->layout; | |
19450 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); | |
19451 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); | |
19452 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; | |
19453 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; | |
19454 layout->row.templates[layout->row.columns++] = -1.0f; | |
19455 } | |
19456 | |
19457 NK_API void | |
19458 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width) | |
19459 { | |
19460 struct nk_window *win; | |
19461 struct nk_panel *layout; | |
19462 | |
19463 NK_ASSERT(ctx); | |
19464 NK_ASSERT(ctx->current); | |
19465 NK_ASSERT(ctx->current->layout); | |
19466 if (!ctx || !ctx->current || !ctx->current->layout) | |
19467 return; | |
19468 | |
19469 win = ctx->current; | |
19470 layout = win->layout; | |
19471 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); | |
19472 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); | |
19473 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; | |
19474 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; | |
19475 layout->row.templates[layout->row.columns++] = -min_width; | |
19476 } | |
19477 | |
19478 NK_API void | |
19479 nk_layout_row_template_push_static(struct nk_context *ctx, float width) | |
19480 { | |
19481 struct nk_window *win; | |
19482 struct nk_panel *layout; | |
19483 | |
19484 NK_ASSERT(ctx); | |
19485 NK_ASSERT(ctx->current); | |
19486 NK_ASSERT(ctx->current->layout); | |
19487 if (!ctx || !ctx->current || !ctx->current->layout) | |
19488 return; | |
19489 | |
19490 win = ctx->current; | |
19491 layout = win->layout; | |
19492 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); | |
19493 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); | |
19494 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; | |
19495 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; | |
19496 layout->row.templates[layout->row.columns++] = width; | |
19497 } | |
19498 | |
19499 NK_API void | |
19500 nk_layout_row_template_end(struct nk_context *ctx) | |
19501 { | |
19502 struct nk_window *win; | |
19503 struct nk_panel *layout; | |
19504 | |
19505 int i = 0; | |
19506 int variable_count = 0; | |
19507 int min_variable_count = 0; | |
19508 float min_fixed_width = 0.0f; | |
19509 float total_fixed_width = 0.0f; | |
19510 float max_variable_width = 0.0f; | |
19511 | |
19512 NK_ASSERT(ctx); | |
19513 NK_ASSERT(ctx->current); | |
19514 NK_ASSERT(ctx->current->layout); | |
19515 if (!ctx || !ctx->current || !ctx->current->layout) | |
19516 return; | |
19517 | |
19518 win = ctx->current; | |
19519 layout = win->layout; | |
19520 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); | |
19521 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; | |
19522 for (i = 0; i < layout->row.columns; ++i) { | |
19523 float width = layout->row.templates[i]; | |
19524 if (width >= 0.0f) { | |
19525 total_fixed_width += width; | |
19526 min_fixed_width += width; | |
19527 } else if (width < -1.0f) { | |
19528 width = -width; | |
19529 total_fixed_width += width; | |
19530 max_variable_width = NK_MAX(max_variable_width, width); | |
19531 variable_count++; | |
19532 } else { | |
19533 min_variable_count++; | |
19534 variable_count++; | |
19535 } | |
19536 } | |
19537 if (variable_count) { | |
19538 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, | |
19539 layout->bounds.w, layout->row.columns); | |
19540 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count; | |
19541 int enough_space = var_width >= max_variable_width; | |
19542 if (!enough_space) | |
19543 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count; | |
19544 for (i = 0; i < layout->row.columns; ++i) { | |
19545 float *width = &layout->row.templates[i]; | |
19546 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width; | |
19547 } | |
19548 } | |
19549 } | |
19550 | |
19551 NK_API void | |
19552 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, | |
19553 float height, int widget_count) | |
19554 { | |
19555 struct nk_window *win; | |
19556 struct nk_panel *layout; | |
19557 | |
19558 NK_ASSERT(ctx); | |
19559 NK_ASSERT(ctx->current); | |
19560 NK_ASSERT(ctx->current->layout); | |
19561 if (!ctx || !ctx->current || !ctx->current->layout) | |
19562 return; | |
19563 | |
19564 win = ctx->current; | |
19565 layout = win->layout; | |
19566 nk_panel_layout(ctx, win, height, widget_count); | |
19567 if (fmt == NK_STATIC) | |
19568 layout->row.type = NK_LAYOUT_STATIC_FREE; | |
19569 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; | |
19570 | |
19571 layout->row.ratio = 0; | |
19572 layout->row.filled = 0; | |
19573 layout->row.item_width = 0; | |
19574 layout->row.item_offset = 0; | |
19575 } | |
19576 | |
19577 NK_API void | |
19578 nk_layout_space_end(struct nk_context *ctx) | |
19579 { | |
19580 struct nk_window *win; | |
19581 struct nk_panel *layout; | |
19582 | |
19583 NK_ASSERT(ctx); | |
19584 NK_ASSERT(ctx->current); | |
19585 NK_ASSERT(ctx->current->layout); | |
19586 if (!ctx || !ctx->current || !ctx->current->layout) | |
19587 return; | |
19588 | |
19589 win = ctx->current; | |
19590 layout = win->layout; | |
19591 layout->row.item_width = 0; | |
19592 layout->row.item_height = 0; | |
19593 layout->row.item_offset = 0; | |
19594 nk_zero(&layout->row.item, sizeof(layout->row.item)); | |
19595 } | |
19596 | |
19597 NK_API void | |
19598 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) | |
19599 { | |
19600 struct nk_window *win; | |
19601 struct nk_panel *layout; | |
19602 | |
19603 NK_ASSERT(ctx); | |
19604 NK_ASSERT(ctx->current); | |
19605 NK_ASSERT(ctx->current->layout); | |
19606 if (!ctx || !ctx->current || !ctx->current->layout) | |
19607 return; | |
19608 | |
19609 win = ctx->current; | |
19610 layout = win->layout; | |
19611 layout->row.item = rect; | |
19612 } | |
19613 | |
19614 NK_API struct nk_rect | |
19615 nk_layout_space_bounds(struct nk_context *ctx) | |
19616 { | |
19617 struct nk_rect ret; | |
19618 struct nk_window *win; | |
19619 struct nk_panel *layout; | |
19620 | |
19621 NK_ASSERT(ctx); | |
19622 NK_ASSERT(ctx->current); | |
19623 NK_ASSERT(ctx->current->layout); | |
19624 win = ctx->current; | |
19625 layout = win->layout; | |
19626 | |
19627 ret.x = layout->clip.x; | |
19628 ret.y = layout->clip.y; | |
19629 ret.w = layout->clip.w; | |
19630 ret.h = layout->row.height; | |
19631 return ret; | |
19632 } | |
19633 | |
19634 NK_API struct nk_rect | |
19635 nk_layout_widget_bounds(struct nk_context *ctx) | |
19636 { | |
19637 struct nk_rect ret; | |
19638 struct nk_window *win; | |
19639 struct nk_panel *layout; | |
19640 | |
19641 NK_ASSERT(ctx); | |
19642 NK_ASSERT(ctx->current); | |
19643 NK_ASSERT(ctx->current->layout); | |
19644 win = ctx->current; | |
19645 layout = win->layout; | |
19646 | |
19647 ret.x = layout->at_x; | |
19648 ret.y = layout->at_y; | |
19649 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0); | |
19650 ret.h = layout->row.height; | |
19651 return ret; | |
19652 } | |
19653 | |
19654 NK_API struct nk_vec2 | |
19655 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) | |
19656 { | |
19657 struct nk_window *win; | |
19658 struct nk_panel *layout; | |
19659 | |
19660 NK_ASSERT(ctx); | |
19661 NK_ASSERT(ctx->current); | |
19662 NK_ASSERT(ctx->current->layout); | |
19663 win = ctx->current; | |
19664 layout = win->layout; | |
19665 | |
19666 ret.x += layout->at_x - (float)*layout->offset_x; | |
19667 ret.y += layout->at_y - (float)*layout->offset_y; | |
19668 return ret; | |
19669 } | |
19670 | |
19671 NK_API struct nk_vec2 | |
19672 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) | |
19673 { | |
19674 struct nk_window *win; | |
19675 struct nk_panel *layout; | |
19676 | |
19677 NK_ASSERT(ctx); | |
19678 NK_ASSERT(ctx->current); | |
19679 NK_ASSERT(ctx->current->layout); | |
19680 win = ctx->current; | |
19681 layout = win->layout; | |
19682 | |
19683 ret.x += -layout->at_x + (float)*layout->offset_x; | |
19684 ret.y += -layout->at_y + (float)*layout->offset_y; | |
19685 return ret; | |
19686 } | |
19687 | |
19688 NK_API struct nk_rect | |
19689 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) | |
19690 { | |
19691 struct nk_window *win; | |
19692 struct nk_panel *layout; | |
19693 | |
19694 NK_ASSERT(ctx); | |
19695 NK_ASSERT(ctx->current); | |
19696 NK_ASSERT(ctx->current->layout); | |
19697 win = ctx->current; | |
19698 layout = win->layout; | |
19699 | |
19700 ret.x += layout->at_x - (float)*layout->offset_x; | |
19701 ret.y += layout->at_y - (float)*layout->offset_y; | |
19702 return ret; | |
19703 } | |
19704 | |
19705 NK_API struct nk_rect | |
19706 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) | |
19707 { | |
19708 struct nk_window *win; | |
19709 struct nk_panel *layout; | |
19710 | |
19711 NK_ASSERT(ctx); | |
19712 NK_ASSERT(ctx->current); | |
19713 NK_ASSERT(ctx->current->layout); | |
19714 win = ctx->current; | |
19715 layout = win->layout; | |
19716 | |
19717 ret.x += -layout->at_x + (float)*layout->offset_x; | |
19718 ret.y += -layout->at_y + (float)*layout->offset_y; | |
19719 return ret; | |
19720 } | |
19721 | |
19722 NK_INTERN void | |
19723 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) | |
19724 { | |
19725 struct nk_panel *layout = win->layout; | |
19726 struct nk_vec2 spacing = ctx->style.window.spacing; | |
19727 const float row_height = layout->row.height - spacing.y; | |
19728 nk_panel_layout(ctx, win, row_height, layout->row.columns); | |
19729 } | |
19730 | |
19731 NK_INTERN void | |
19732 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, | |
19733 struct nk_window *win, int modify) | |
19734 { | |
19735 struct nk_panel *layout; | |
19736 const struct nk_style *style; | |
19737 | |
19738 struct nk_vec2 spacing; | |
19739 struct nk_vec2 padding; | |
19740 | |
19741 float item_offset = 0; | |
19742 float item_width = 0; | |
19743 float item_spacing = 0; | |
19744 float panel_space = 0; | |
19745 | |
19746 NK_ASSERT(ctx); | |
19747 NK_ASSERT(ctx->current); | |
19748 NK_ASSERT(ctx->current->layout); | |
19749 if (!ctx || !ctx->current || !ctx->current->layout) | |
19750 return; | |
19751 | |
19752 win = ctx->current; | |
19753 layout = win->layout; | |
19754 style = &ctx->style; | |
19755 NK_ASSERT(bounds); | |
19756 | |
19757 spacing = style->window.spacing; | |
19758 padding = nk_panel_get_padding(style, layout->type); | |
19759 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, | |
19760 layout->bounds.w, layout->row.columns); | |
19761 | |
19762 /* calculate the width of one item inside the current layout space */ | |
19763 switch (layout->row.type) { | |
19764 case NK_LAYOUT_DYNAMIC_FIXED: { | |
19765 /* scaling fixed size widgets item width */ | |
19766 item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns; | |
19767 item_offset = (float)layout->row.index * item_width; | |
19768 item_spacing = (float)layout->row.index * spacing.x; | |
19769 } break; | |
19770 case NK_LAYOUT_DYNAMIC_ROW: { | |
19771 /* scaling single ratio widget width */ | |
19772 item_width = layout->row.item_width * panel_space; | |
19773 item_offset = layout->row.item_offset; | |
19774 item_spacing = 0; | |
19775 | |
19776 if (modify) { | |
19777 layout->row.item_offset += item_width + spacing.x; | |
19778 layout->row.filled += layout->row.item_width; | |
19779 layout->row.index = 0; | |
19780 } | |
19781 } break; | |
19782 case NK_LAYOUT_DYNAMIC_FREE: { | |
19783 /* panel width depended free widget placing */ | |
19784 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); | |
19785 bounds->x -= (float)*layout->offset_x; | |
19786 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); | |
19787 bounds->y -= (float)*layout->offset_y; | |
19788 bounds->w = layout->bounds.w * layout->row.item.w; | |
19789 bounds->h = layout->row.height * layout->row.item.h; | |
19790 return; | |
19791 } break; | |
19792 case NK_LAYOUT_DYNAMIC: { | |
19793 /* scaling arrays of panel width ratios for every widget */ | |
19794 float ratio; | |
19795 NK_ASSERT(layout->row.ratio); | |
19796 ratio = (layout->row.ratio[layout->row.index] < 0) ? | |
19797 layout->row.item_width : layout->row.ratio[layout->row.index]; | |
19798 | |
19799 item_spacing = (float)layout->row.index * spacing.x; | |
19800 item_width = (ratio * panel_space); | |
19801 item_offset = layout->row.item_offset; | |
19802 | |
19803 if (modify) { | |
19804 layout->row.item_offset += item_width; | |
19805 layout->row.filled += ratio; | |
19806 } | |
19807 } break; | |
19808 case NK_LAYOUT_STATIC_FIXED: { | |
19809 /* non-scaling fixed widgets item width */ | |
19810 item_width = layout->row.item_width; | |
19811 item_offset = (float)layout->row.index * item_width; | |
19812 item_spacing = (float)layout->row.index * spacing.x; | |
19813 } break; | |
19814 case NK_LAYOUT_STATIC_ROW: { | |
19815 /* scaling single ratio widget width */ | |
19816 item_width = layout->row.item_width; | |
19817 item_offset = layout->row.item_offset; | |
19818 item_spacing = (float)layout->row.index * spacing.x; | |
19819 if (modify) layout->row.item_offset += item_width; | |
19820 } break; | |
19821 case NK_LAYOUT_STATIC_FREE: { | |
19822 /* free widget placing */ | |
19823 bounds->x = layout->at_x + layout->row.item.x; | |
19824 bounds->w = layout->row.item.w; | |
19825 if (((bounds->x + bounds->w) > layout->max_x) && modify) | |
19826 layout->max_x = (bounds->x + bounds->w); | |
19827 bounds->x -= (float)*layout->offset_x; | |
19828 bounds->y = layout->at_y + layout->row.item.y; | |
19829 bounds->y -= (float)*layout->offset_y; | |
19830 bounds->h = layout->row.item.h; | |
19831 return; | |
19832 } break; | |
19833 case NK_LAYOUT_STATIC: { | |
19834 /* non-scaling array of panel pixel width for every widget */ | |
19835 item_spacing = (float)layout->row.index * spacing.x; | |
19836 item_width = layout->row.ratio[layout->row.index]; | |
19837 item_offset = layout->row.item_offset; | |
19838 if (modify) layout->row.item_offset += item_width; | |
19839 } break; | |
19840 case NK_LAYOUT_TEMPLATE: { | |
19841 /* stretchy row layout with combined dynamic/static widget width*/ | |
19842 NK_ASSERT(layout->row.index < layout->row.columns); | |
19843 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); | |
19844 item_width = layout->row.templates[layout->row.index]; | |
19845 item_offset = layout->row.item_offset; | |
19846 item_spacing = (float)layout->row.index * spacing.x; | |
19847 if (modify) layout->row.item_offset += item_width; | |
19848 } break; | |
19849 default: NK_ASSERT(0); break; | |
19850 }; | |
19851 | |
19852 /* set the bounds of the newly allocated widget */ | |
19853 bounds->w = item_width; | |
19854 bounds->h = layout->row.height - spacing.y; | |
19855 bounds->y = layout->at_y - (float)*layout->offset_y; | |
19856 bounds->x = layout->at_x + item_offset + item_spacing + padding.x; | |
19857 if (((bounds->x + bounds->w) > layout->max_x) && modify) | |
19858 layout->max_x = bounds->x + bounds->w; | |
19859 bounds->x -= (float)*layout->offset_x; | |
19860 } | |
19861 | |
19862 NK_INTERN void | |
19863 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) | |
19864 { | |
19865 struct nk_window *win; | |
19866 struct nk_panel *layout; | |
19867 | |
19868 NK_ASSERT(ctx); | |
19869 NK_ASSERT(ctx->current); | |
19870 NK_ASSERT(ctx->current->layout); | |
19871 if (!ctx || !ctx->current || !ctx->current->layout) | |
19872 return; | |
19873 | |
19874 /* check if the end of the row has been hit and begin new row if so */ | |
19875 win = ctx->current; | |
19876 layout = win->layout; | |
19877 if (layout->row.index >= layout->row.columns) | |
19878 nk_panel_alloc_row(ctx, win); | |
19879 | |
19880 /* calculate widget position and size */ | |
19881 nk_layout_widget_space(bounds, ctx, win, nk_true); | |
19882 layout->row.index++; | |
19883 } | |
19884 | |
19885 NK_INTERN void | |
19886 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) | |
19887 { | |
19888 float y; | |
19889 int index; | |
19890 struct nk_window *win; | |
19891 struct nk_panel *layout; | |
19892 | |
19893 NK_ASSERT(ctx); | |
19894 NK_ASSERT(ctx->current); | |
19895 NK_ASSERT(ctx->current->layout); | |
19896 if (!ctx || !ctx->current || !ctx->current->layout) | |
19897 return; | |
19898 | |
19899 win = ctx->current; | |
19900 layout = win->layout; | |
19901 y = layout->at_y; | |
19902 index = layout->row.index; | |
19903 if (layout->row.index >= layout->row.columns) { | |
19904 layout->at_y += layout->row.height; | |
19905 layout->row.index = 0; | |
19906 } | |
19907 nk_layout_widget_space(bounds, ctx, win, nk_false); | |
19908 layout->at_y = y; | |
19909 layout->row.index = index; | |
19910 } | |
19911 | |
19912 NK_INTERN int | |
19913 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, | |
19914 struct nk_image *img, const char *title, enum nk_collapse_states *state) | |
19915 { | |
19916 struct nk_window *win; | |
19917 struct nk_panel *layout; | |
19918 const struct nk_style *style; | |
19919 struct nk_command_buffer *out; | |
19920 const struct nk_input *in; | |
19921 const struct nk_style_button *button; | |
19922 enum nk_symbol_type symbol; | |
19923 float row_height; | |
19924 | |
19925 struct nk_vec2 item_spacing; | |
19926 struct nk_rect header = {0,0,0,0}; | |
19927 struct nk_rect sym = {0,0,0,0}; | |
19928 struct nk_text text; | |
19929 | |
19930 nk_flags ws = 0; | |
19931 enum nk_widget_layout_states widget_state; | |
19932 | |
19933 NK_ASSERT(ctx); | |
19934 NK_ASSERT(ctx->current); | |
19935 NK_ASSERT(ctx->current->layout); | |
19936 if (!ctx || !ctx->current || !ctx->current->layout) | |
19937 return 0; | |
19938 | |
19939 /* cache some data */ | |
19940 win = ctx->current; | |
19941 layout = win->layout; | |
19942 out = &win->buffer; | |
19943 style = &ctx->style; | |
19944 item_spacing = style->window.spacing; | |
19945 | |
19946 /* calculate header bounds and draw background */ | |
19947 row_height = style->font->height + 2 * style->tab.padding.y; | |
19948 nk_layout_set_min_row_height(ctx, row_height); | |
19949 nk_layout_row_dynamic(ctx, row_height, 1); | |
19950 nk_layout_reset_min_row_height(ctx); | |
19951 | |
19952 widget_state = nk_widget(&header, ctx); | |
19953 if (type == NK_TREE_TAB) { | |
19954 const struct nk_style_item *background = &style->tab.background; | |
19955 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
19956 nk_draw_image(out, header, &background->data.image, nk_white); | |
19957 text.background = nk_rgba(0,0,0,0); | |
19958 } else { | |
19959 text.background = background->data.color; | |
19960 nk_fill_rect(out, header, 0, style->tab.border_color); | |
19961 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), | |
19962 style->tab.rounding, background->data.color); | |
19963 } | |
19964 } else text.background = style->window.background; | |
19965 | |
19966 /* update node state */ | |
19967 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; | |
19968 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; | |
19969 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) | |
19970 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; | |
19971 | |
19972 /* select correct button style */ | |
19973 if (*state == NK_MAXIMIZED) { | |
19974 symbol = style->tab.sym_maximize; | |
19975 if (type == NK_TREE_TAB) | |
19976 button = &style->tab.tab_maximize_button; | |
19977 else button = &style->tab.node_maximize_button; | |
19978 } else { | |
19979 symbol = style->tab.sym_minimize; | |
19980 if (type == NK_TREE_TAB) | |
19981 button = &style->tab.tab_minimize_button; | |
19982 else button = &style->tab.node_minimize_button; | |
19983 } | |
19984 | |
19985 {/* draw triangle button */ | |
19986 sym.w = sym.h = style->font->height; | |
19987 sym.y = header.y + style->tab.padding.y; | |
19988 sym.x = header.x + style->tab.padding.x; | |
19989 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, | |
19990 button, 0, style->font); | |
19991 | |
19992 if (img) { | |
19993 /* draw optional image icon */ | |
19994 sym.x = sym.x + sym.w + 4 * item_spacing.x; | |
19995 nk_draw_image(&win->buffer, sym, img, nk_white); | |
19996 sym.w = style->font->height + style->tab.spacing.x;} | |
19997 } | |
19998 | |
19999 {/* draw label */ | |
20000 struct nk_rect label; | |
20001 header.w = NK_MAX(header.w, sym.w + item_spacing.x); | |
20002 label.x = sym.x + sym.w + item_spacing.x; | |
20003 label.y = sym.y; | |
20004 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); | |
20005 label.h = style->font->height; | |
20006 text.text = style->tab.text; | |
20007 text.padding = nk_vec2(0,0); | |
20008 nk_widget_text(out, label, title, nk_strlen(title), &text, | |
20009 NK_TEXT_LEFT, style->font);} | |
20010 | |
20011 /* increase x-axis cursor widget position pointer */ | |
20012 if (*state == NK_MAXIMIZED) { | |
20013 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; | |
20014 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); | |
20015 layout->bounds.w -= (style->tab.indent + style->window.padding.x); | |
20016 layout->row.tree_depth++; | |
20017 return nk_true; | |
20018 } else return nk_false; | |
20019 } | |
20020 | |
20021 NK_INTERN int | |
20022 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, | |
20023 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, | |
20024 const char *hash, int len, int line) | |
20025 { | |
20026 struct nk_window *win = ctx->current; | |
20027 int title_len = 0; | |
20028 nk_hash tree_hash = 0; | |
20029 nk_uint *state = 0; | |
20030 | |
20031 /* retrieve tree state from internal widget state tables */ | |
20032 if (!hash) { | |
20033 title_len = (int)nk_strlen(title); | |
20034 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); | |
20035 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); | |
20036 state = nk_find_value(win, tree_hash); | |
20037 if (!state) { | |
20038 state = nk_add_value(ctx, win, tree_hash, 0); | |
20039 *state = initial_state; | |
20040 } | |
20041 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); | |
20042 } | |
20043 | |
20044 NK_API int | |
20045 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, | |
20046 const char *title, enum nk_collapse_states *state) | |
20047 {return nk_tree_state_base(ctx, type, 0, title, state);} | |
20048 | |
20049 NK_API int | |
20050 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, | |
20051 struct nk_image img, const char *title, enum nk_collapse_states *state) | |
20052 {return nk_tree_state_base(ctx, type, &img, title, state);} | |
20053 | |
20054 NK_API void | |
20055 nk_tree_state_pop(struct nk_context *ctx) | |
20056 { | |
20057 struct nk_window *win = 0; | |
20058 struct nk_panel *layout = 0; | |
20059 | |
20060 NK_ASSERT(ctx); | |
20061 NK_ASSERT(ctx->current); | |
20062 NK_ASSERT(ctx->current->layout); | |
20063 if (!ctx || !ctx->current || !ctx->current->layout) | |
20064 return; | |
20065 | |
20066 win = ctx->current; | |
20067 layout = win->layout; | |
20068 layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x; | |
20069 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; | |
20070 NK_ASSERT(layout->row.tree_depth); | |
20071 layout->row.tree_depth--; | |
20072 } | |
20073 | |
20074 NK_API int | |
20075 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, | |
20076 const char *title, enum nk_collapse_states initial_state, | |
20077 const char *hash, int len, int line) | |
20078 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);} | |
20079 | |
20080 NK_API int | |
20081 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, | |
20082 struct nk_image img, const char *title, enum nk_collapse_states initial_state, | |
20083 const char *hash, int len,int seed) | |
20084 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);} | |
20085 | |
20086 NK_API void | |
20087 nk_tree_pop(struct nk_context *ctx) | |
20088 {nk_tree_state_pop(ctx);} | |
20089 | |
20090 /*---------------------------------------------------------------- | |
20091 * | |
20092 * WIDGETS | |
20093 * | |
20094 * --------------------------------------------------------------*/ | |
20095 NK_API struct nk_rect | |
20096 nk_widget_bounds(struct nk_context *ctx) | |
20097 { | |
20098 struct nk_rect bounds; | |
20099 NK_ASSERT(ctx); | |
20100 NK_ASSERT(ctx->current); | |
20101 if (!ctx || !ctx->current) | |
20102 return nk_rect(0,0,0,0); | |
20103 nk_layout_peek(&bounds, ctx); | |
20104 return bounds; | |
20105 } | |
20106 | |
20107 NK_API struct nk_vec2 | |
20108 nk_widget_position(struct nk_context *ctx) | |
20109 { | |
20110 struct nk_rect bounds; | |
20111 NK_ASSERT(ctx); | |
20112 NK_ASSERT(ctx->current); | |
20113 if (!ctx || !ctx->current) | |
20114 return nk_vec2(0,0); | |
20115 | |
20116 nk_layout_peek(&bounds, ctx); | |
20117 return nk_vec2(bounds.x, bounds.y); | |
20118 } | |
20119 | |
20120 NK_API struct nk_vec2 | |
20121 nk_widget_size(struct nk_context *ctx) | |
20122 { | |
20123 struct nk_rect bounds; | |
20124 NK_ASSERT(ctx); | |
20125 NK_ASSERT(ctx->current); | |
20126 if (!ctx || !ctx->current) | |
20127 return nk_vec2(0,0); | |
20128 | |
20129 nk_layout_peek(&bounds, ctx); | |
20130 return nk_vec2(bounds.w, bounds.h); | |
20131 } | |
20132 | |
20133 NK_API float | |
20134 nk_widget_width(struct nk_context *ctx) | |
20135 { | |
20136 struct nk_rect bounds; | |
20137 NK_ASSERT(ctx); | |
20138 NK_ASSERT(ctx->current); | |
20139 if (!ctx || !ctx->current) | |
20140 return 0; | |
20141 | |
20142 nk_layout_peek(&bounds, ctx); | |
20143 return bounds.w; | |
20144 } | |
20145 | |
20146 NK_API float | |
20147 nk_widget_height(struct nk_context *ctx) | |
20148 { | |
20149 struct nk_rect bounds; | |
20150 NK_ASSERT(ctx); | |
20151 NK_ASSERT(ctx->current); | |
20152 if (!ctx || !ctx->current) | |
20153 return 0; | |
20154 | |
20155 nk_layout_peek(&bounds, ctx); | |
20156 return bounds.h; | |
20157 } | |
20158 | |
20159 NK_API int | |
20160 nk_widget_is_hovered(struct nk_context *ctx) | |
20161 { | |
20162 struct nk_rect c, v; | |
20163 struct nk_rect bounds; | |
20164 NK_ASSERT(ctx); | |
20165 NK_ASSERT(ctx->current); | |
20166 if (!ctx || !ctx->current || ctx->active != ctx->current) | |
20167 return 0; | |
20168 | |
20169 c = ctx->current->layout->clip; | |
20170 c.x = (float)((int)c.x); | |
20171 c.y = (float)((int)c.y); | |
20172 c.w = (float)((int)c.w); | |
20173 c.h = (float)((int)c.h); | |
20174 | |
20175 nk_layout_peek(&bounds, ctx); | |
20176 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); | |
20177 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) | |
20178 return 0; | |
20179 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds); | |
20180 } | |
20181 | |
20182 NK_API int | |
20183 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) | |
20184 { | |
20185 struct nk_rect c, v; | |
20186 struct nk_rect bounds; | |
20187 NK_ASSERT(ctx); | |
20188 NK_ASSERT(ctx->current); | |
20189 if (!ctx || !ctx->current || ctx->active != ctx->current) | |
20190 return 0; | |
20191 | |
20192 c = ctx->current->layout->clip; | |
20193 c.x = (float)((int)c.x); | |
20194 c.y = (float)((int)c.y); | |
20195 c.w = (float)((int)c.w); | |
20196 c.h = (float)((int)c.h); | |
20197 | |
20198 nk_layout_peek(&bounds, ctx); | |
20199 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); | |
20200 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) | |
20201 return 0; | |
20202 return nk_input_mouse_clicked(&ctx->input, btn, bounds); | |
20203 } | |
20204 | |
20205 NK_API int | |
20206 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down) | |
20207 { | |
20208 struct nk_rect c, v; | |
20209 struct nk_rect bounds; | |
20210 NK_ASSERT(ctx); | |
20211 NK_ASSERT(ctx->current); | |
20212 if (!ctx || !ctx->current || ctx->active != ctx->current) | |
20213 return 0; | |
20214 | |
20215 c = ctx->current->layout->clip; | |
20216 c.x = (float)((int)c.x); | |
20217 c.y = (float)((int)c.y); | |
20218 c.w = (float)((int)c.w); | |
20219 c.h = (float)((int)c.h); | |
20220 | |
20221 nk_layout_peek(&bounds, ctx); | |
20222 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); | |
20223 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) | |
20224 return 0; | |
20225 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); | |
20226 } | |
20227 | |
20228 NK_API enum nk_widget_layout_states | |
20229 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) | |
20230 { | |
20231 struct nk_rect c, v; | |
20232 struct nk_window *win; | |
20233 struct nk_panel *layout; | |
20234 const struct nk_input *in; | |
20235 | |
20236 NK_ASSERT(ctx); | |
20237 NK_ASSERT(ctx->current); | |
20238 NK_ASSERT(ctx->current->layout); | |
20239 if (!ctx || !ctx->current || !ctx->current->layout) | |
20240 return NK_WIDGET_INVALID; | |
20241 | |
20242 /* allocate space and check if the widget needs to be updated and drawn */ | |
20243 nk_panel_alloc_space(bounds, ctx); | |
20244 win = ctx->current; | |
20245 layout = win->layout; | |
20246 in = &ctx->input; | |
20247 c = layout->clip; | |
20248 | |
20249 /* if one of these triggers you forgot to add an `if` condition around either | |
20250 a window, group, popup, combobox or contextual menu `begin` and `end` block. | |
20251 Example: | |
20252 if (nk_begin(...) {...} nk_end(...); or | |
20253 if (nk_group_begin(...) { nk_group_end(...);} */ | |
20254 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); | |
20255 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); | |
20256 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); | |
20257 | |
20258 /* need to convert to int here to remove floating point errors */ | |
20259 bounds->x = (float)((int)bounds->x); | |
20260 bounds->y = (float)((int)bounds->y); | |
20261 bounds->w = (float)((int)bounds->w); | |
20262 bounds->h = (float)((int)bounds->h); | |
20263 | |
20264 c.x = (float)((int)c.x); | |
20265 c.y = (float)((int)c.y); | |
20266 c.w = (float)((int)c.w); | |
20267 c.h = (float)((int)c.h); | |
20268 | |
20269 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h); | |
20270 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h)) | |
20271 return NK_WIDGET_INVALID; | |
20272 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h)) | |
20273 return NK_WIDGET_ROM; | |
20274 return NK_WIDGET_VALID; | |
20275 } | |
20276 | |
20277 NK_API enum nk_widget_layout_states | |
20278 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, | |
20279 struct nk_vec2 item_padding) | |
20280 { | |
20281 /* update the bounds to stand without padding */ | |
20282 struct nk_window *win; | |
20283 struct nk_style *style; | |
20284 struct nk_panel *layout; | |
20285 enum nk_widget_layout_states state; | |
20286 struct nk_vec2 panel_padding; | |
20287 | |
20288 NK_ASSERT(ctx); | |
20289 NK_ASSERT(ctx->current); | |
20290 NK_ASSERT(ctx->current->layout); | |
20291 if (!ctx || !ctx->current || !ctx->current->layout) | |
20292 return NK_WIDGET_INVALID; | |
20293 | |
20294 win = ctx->current; | |
20295 style = &ctx->style; | |
20296 layout = win->layout; | |
20297 state = nk_widget(bounds, ctx); | |
20298 | |
20299 panel_padding = nk_panel_get_padding(style, layout->type); | |
20300 if (layout->row.index == 1) { | |
20301 bounds->w += panel_padding.x; | |
20302 bounds->x -= panel_padding.x; | |
20303 } else bounds->x -= item_padding.x; | |
20304 | |
20305 if (layout->row.index == layout->row.columns) | |
20306 bounds->w += panel_padding.x; | |
20307 else bounds->w += item_padding.x; | |
20308 return state; | |
20309 } | |
20310 | |
20311 /*---------------------------------------------------------------- | |
20312 * | |
20313 * MISC | |
20314 * | |
20315 * --------------------------------------------------------------*/ | |
20316 NK_API void | |
20317 nk_spacing(struct nk_context *ctx, int cols) | |
20318 { | |
20319 struct nk_window *win; | |
20320 struct nk_panel *layout; | |
20321 struct nk_rect none; | |
20322 int i, index, rows; | |
20323 | |
20324 NK_ASSERT(ctx); | |
20325 NK_ASSERT(ctx->current); | |
20326 NK_ASSERT(ctx->current->layout); | |
20327 if (!ctx || !ctx->current || !ctx->current->layout) | |
20328 return; | |
20329 | |
20330 /* spacing over row boundaries */ | |
20331 win = ctx->current; | |
20332 layout = win->layout; | |
20333 index = (layout->row.index + cols) % layout->row.columns; | |
20334 rows = (layout->row.index + cols) / layout->row.columns; | |
20335 if (rows) { | |
20336 for (i = 0; i < rows; ++i) | |
20337 nk_panel_alloc_row(ctx, win); | |
20338 cols = index; | |
20339 } | |
20340 /* non table layout need to allocate space */ | |
20341 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && | |
20342 layout->row.type != NK_LAYOUT_STATIC_FIXED) { | |
20343 for (i = 0; i < cols; ++i) | |
20344 nk_panel_alloc_space(&none, ctx); | |
20345 } | |
20346 layout->row.index = index; | |
20347 } | |
20348 | |
20349 /*---------------------------------------------------------------- | |
20350 * | |
20351 * TEXT | |
20352 * | |
20353 * --------------------------------------------------------------*/ | |
20354 NK_API void | |
20355 nk_text_colored(struct nk_context *ctx, const char *str, int len, | |
20356 nk_flags alignment, struct nk_color color) | |
20357 { | |
20358 struct nk_window *win; | |
20359 const struct nk_style *style; | |
20360 | |
20361 struct nk_vec2 item_padding; | |
20362 struct nk_rect bounds; | |
20363 struct nk_text text; | |
20364 | |
20365 NK_ASSERT(ctx); | |
20366 NK_ASSERT(ctx->current); | |
20367 NK_ASSERT(ctx->current->layout); | |
20368 if (!ctx || !ctx->current || !ctx->current->layout) return; | |
20369 | |
20370 win = ctx->current; | |
20371 style = &ctx->style; | |
20372 nk_panel_alloc_space(&bounds, ctx); | |
20373 item_padding = style->text.padding; | |
20374 | |
20375 text.padding.x = item_padding.x; | |
20376 text.padding.y = item_padding.y; | |
20377 text.background = style->window.background; | |
20378 text.text = color; | |
20379 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); | |
20380 } | |
20381 | |
20382 NK_API void | |
20383 nk_text_wrap_colored(struct nk_context *ctx, const char *str, | |
20384 int len, struct nk_color color) | |
20385 { | |
20386 struct nk_window *win; | |
20387 const struct nk_style *style; | |
20388 | |
20389 struct nk_vec2 item_padding; | |
20390 struct nk_rect bounds; | |
20391 struct nk_text text; | |
20392 | |
20393 NK_ASSERT(ctx); | |
20394 NK_ASSERT(ctx->current); | |
20395 NK_ASSERT(ctx->current->layout); | |
20396 if (!ctx || !ctx->current || !ctx->current->layout) return; | |
20397 | |
20398 win = ctx->current; | |
20399 style = &ctx->style; | |
20400 nk_panel_alloc_space(&bounds, ctx); | |
20401 item_padding = style->text.padding; | |
20402 | |
20403 text.padding.x = item_padding.x; | |
20404 text.padding.y = item_padding.y; | |
20405 text.background = style->window.background; | |
20406 text.text = color; | |
20407 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); | |
20408 } | |
20409 | |
20410 #ifdef NK_INCLUDE_STANDARD_VARARGS | |
20411 NK_API void | |
20412 nk_labelf_colored(struct nk_context *ctx, nk_flags flags, | |
20413 struct nk_color color, const char *fmt, ...) | |
20414 { | |
20415 char buf[256]; | |
20416 va_list args; | |
20417 va_start(args, fmt); | |
20418 nk_strfmt(buf, NK_LEN(buf), fmt, args); | |
20419 nk_label_colored(ctx, buf, flags, color); | |
20420 va_end(args); | |
20421 } | |
20422 | |
20423 NK_API void | |
20424 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, | |
20425 const char *fmt, ...) | |
20426 { | |
20427 char buf[256]; | |
20428 va_list args; | |
20429 va_start(args, fmt); | |
20430 nk_strfmt(buf, NK_LEN(buf), fmt, args); | |
20431 nk_label_colored_wrap(ctx, buf, color); | |
20432 va_end(args); | |
20433 } | |
20434 | |
20435 NK_API void | |
20436 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) | |
20437 { | |
20438 char buf[256]; | |
20439 va_list args; | |
20440 va_start(args, fmt); | |
20441 nk_strfmt(buf, NK_LEN(buf), fmt, args); | |
20442 nk_label(ctx, buf, flags); | |
20443 va_end(args); | |
20444 } | |
20445 | |
20446 NK_API void | |
20447 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) | |
20448 { | |
20449 char buf[256]; | |
20450 va_list args; | |
20451 va_start(args, fmt); | |
20452 nk_strfmt(buf, NK_LEN(buf), fmt, args); | |
20453 nk_label_wrap(ctx, buf); | |
20454 va_end(args); | |
20455 } | |
20456 | |
20457 NK_API void | |
20458 nk_value_bool(struct nk_context *ctx, const char *prefix, int value) | |
20459 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));} | |
20460 | |
20461 NK_API void | |
20462 nk_value_int(struct nk_context *ctx, const char *prefix, int value) | |
20463 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);} | |
20464 | |
20465 NK_API void | |
20466 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) | |
20467 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);} | |
20468 | |
20469 NK_API void | |
20470 nk_value_float(struct nk_context *ctx, const char *prefix, float value) | |
20471 { | |
20472 double double_value = (double)value; | |
20473 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); | |
20474 } | |
20475 | |
20476 NK_API void | |
20477 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) | |
20478 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);} | |
20479 | |
20480 NK_API void | |
20481 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) | |
20482 { | |
20483 double c[4]; nk_color_dv(c, color); | |
20484 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", | |
20485 p, c[0], c[1], c[2], c[3]); | |
20486 } | |
20487 | |
20488 NK_API void | |
20489 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) | |
20490 { | |
20491 char hex[16]; | |
20492 nk_color_hex_rgba(hex, color); | |
20493 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); | |
20494 } | |
20495 #endif | |
20496 | |
20497 NK_API void | |
20498 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) | |
20499 { | |
20500 NK_ASSERT(ctx); | |
20501 if (!ctx) return; | |
20502 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); | |
20503 } | |
20504 | |
20505 NK_API void | |
20506 nk_text_wrap(struct nk_context *ctx, const char *str, int len) | |
20507 { | |
20508 NK_ASSERT(ctx); | |
20509 if (!ctx) return; | |
20510 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); | |
20511 } | |
20512 | |
20513 NK_API void | |
20514 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) | |
20515 {nk_text(ctx, str, nk_strlen(str), alignment);} | |
20516 | |
20517 NK_API void | |
20518 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, | |
20519 struct nk_color color) | |
20520 {nk_text_colored(ctx, str, nk_strlen(str), align, color);} | |
20521 | |
20522 NK_API void | |
20523 nk_label_wrap(struct nk_context *ctx, const char *str) | |
20524 {nk_text_wrap(ctx, str, nk_strlen(str));} | |
20525 | |
20526 NK_API void | |
20527 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) | |
20528 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);} | |
20529 | |
20530 NK_API void | |
20531 nk_image(struct nk_context *ctx, struct nk_image img) | |
20532 { | |
20533 struct nk_window *win; | |
20534 struct nk_rect bounds; | |
20535 | |
20536 NK_ASSERT(ctx); | |
20537 NK_ASSERT(ctx->current); | |
20538 NK_ASSERT(ctx->current->layout); | |
20539 if (!ctx || !ctx->current || !ctx->current->layout) return; | |
20540 | |
20541 win = ctx->current; | |
20542 if (!nk_widget(&bounds, ctx)) return; | |
20543 nk_draw_image(&win->buffer, bounds, &img, nk_white); | |
20544 } | |
20545 | |
20546 /*---------------------------------------------------------------- | |
20547 * | |
20548 * BUTTON | |
20549 * | |
20550 * --------------------------------------------------------------*/ | |
20551 NK_API void | |
20552 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) | |
20553 { | |
20554 NK_ASSERT(ctx); | |
20555 if (!ctx) return; | |
20556 ctx->button_behavior = behavior; | |
20557 } | |
20558 | |
20559 NK_API int | |
20560 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) | |
20561 { | |
20562 struct nk_config_stack_button_behavior *button_stack; | |
20563 struct nk_config_stack_button_behavior_element *element; | |
20564 | |
20565 NK_ASSERT(ctx); | |
20566 if (!ctx) return 0; | |
20567 | |
20568 button_stack = &ctx->stacks.button_behaviors; | |
20569 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); | |
20570 if (button_stack->head >= (int)NK_LEN(button_stack->elements)) | |
20571 return 0; | |
20572 | |
20573 element = &button_stack->elements[button_stack->head++]; | |
20574 element->address = &ctx->button_behavior; | |
20575 element->old_value = ctx->button_behavior; | |
20576 ctx->button_behavior = behavior; | |
20577 return 1; | |
20578 } | |
20579 | |
20580 NK_API int | |
20581 nk_button_pop_behavior(struct nk_context *ctx) | |
20582 { | |
20583 struct nk_config_stack_button_behavior *button_stack; | |
20584 struct nk_config_stack_button_behavior_element *element; | |
20585 | |
20586 NK_ASSERT(ctx); | |
20587 if (!ctx) return 0; | |
20588 | |
20589 button_stack = &ctx->stacks.button_behaviors; | |
20590 NK_ASSERT(button_stack->head > 0); | |
20591 if (button_stack->head < 1) | |
20592 return 0; | |
20593 | |
20594 element = &button_stack->elements[--button_stack->head]; | |
20595 *element->address = element->old_value; | |
20596 return 1; | |
20597 } | |
20598 | |
20599 NK_API int | |
20600 nk_button_text_styled(struct nk_context *ctx, | |
20601 const struct nk_style_button *style, const char *title, int len) | |
20602 { | |
20603 struct nk_window *win; | |
20604 struct nk_panel *layout; | |
20605 const struct nk_input *in; | |
20606 | |
20607 struct nk_rect bounds; | |
20608 enum nk_widget_layout_states state; | |
20609 | |
20610 NK_ASSERT(ctx); | |
20611 NK_ASSERT(style); | |
20612 NK_ASSERT(ctx->current); | |
20613 NK_ASSERT(ctx->current->layout); | |
20614 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; | |
20615 | |
20616 win = ctx->current; | |
20617 layout = win->layout; | |
20618 state = nk_widget(&bounds, ctx); | |
20619 | |
20620 if (!state) return 0; | |
20621 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20622 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, | |
20623 title, len, style->text_alignment, ctx->button_behavior, | |
20624 style, in, ctx->style.font); | |
20625 } | |
20626 | |
20627 NK_API int | |
20628 nk_button_text(struct nk_context *ctx, const char *title, int len) | |
20629 { | |
20630 NK_ASSERT(ctx); | |
20631 if (!ctx) return 0; | |
20632 return nk_button_text_styled(ctx, &ctx->style.button, title, len); | |
20633 } | |
20634 | |
20635 NK_API int nk_button_label_styled(struct nk_context *ctx, | |
20636 const struct nk_style_button *style, const char *title) | |
20637 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));} | |
20638 | |
20639 NK_API int nk_button_label(struct nk_context *ctx, const char *title) | |
20640 {return nk_button_text(ctx, title, nk_strlen(title));} | |
20641 | |
20642 NK_API int | |
20643 nk_button_color(struct nk_context *ctx, struct nk_color color) | |
20644 { | |
20645 struct nk_window *win; | |
20646 struct nk_panel *layout; | |
20647 const struct nk_input *in; | |
20648 struct nk_style_button button; | |
20649 | |
20650 int ret = 0; | |
20651 struct nk_rect bounds; | |
20652 struct nk_rect content; | |
20653 enum nk_widget_layout_states state; | |
20654 | |
20655 NK_ASSERT(ctx); | |
20656 NK_ASSERT(ctx->current); | |
20657 NK_ASSERT(ctx->current->layout); | |
20658 if (!ctx || !ctx->current || !ctx->current->layout) | |
20659 return 0; | |
20660 | |
20661 win = ctx->current; | |
20662 layout = win->layout; | |
20663 | |
20664 state = nk_widget(&bounds, ctx); | |
20665 if (!state) return 0; | |
20666 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20667 | |
20668 button = ctx->style.button; | |
20669 button.normal = nk_style_item_color(color); | |
20670 button.hover = nk_style_item_color(color); | |
20671 button.active = nk_style_item_color(color); | |
20672 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, | |
20673 &button, in, ctx->button_behavior, &content); | |
20674 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); | |
20675 return ret; | |
20676 } | |
20677 | |
20678 NK_API int | |
20679 nk_button_symbol_styled(struct nk_context *ctx, | |
20680 const struct nk_style_button *style, enum nk_symbol_type symbol) | |
20681 { | |
20682 struct nk_window *win; | |
20683 struct nk_panel *layout; | |
20684 const struct nk_input *in; | |
20685 | |
20686 struct nk_rect bounds; | |
20687 enum nk_widget_layout_states state; | |
20688 | |
20689 NK_ASSERT(ctx); | |
20690 NK_ASSERT(ctx->current); | |
20691 NK_ASSERT(ctx->current->layout); | |
20692 if (!ctx || !ctx->current || !ctx->current->layout) | |
20693 return 0; | |
20694 | |
20695 win = ctx->current; | |
20696 layout = win->layout; | |
20697 state = nk_widget(&bounds, ctx); | |
20698 if (!state) return 0; | |
20699 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20700 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, | |
20701 symbol, ctx->button_behavior, style, in, ctx->style.font); | |
20702 } | |
20703 | |
20704 NK_API int | |
20705 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) | |
20706 { | |
20707 NK_ASSERT(ctx); | |
20708 if (!ctx) return 0; | |
20709 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); | |
20710 } | |
20711 | |
20712 NK_API int | |
20713 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, | |
20714 struct nk_image img) | |
20715 { | |
20716 struct nk_window *win; | |
20717 struct nk_panel *layout; | |
20718 const struct nk_input *in; | |
20719 | |
20720 struct nk_rect bounds; | |
20721 enum nk_widget_layout_states state; | |
20722 | |
20723 NK_ASSERT(ctx); | |
20724 NK_ASSERT(ctx->current); | |
20725 NK_ASSERT(ctx->current->layout); | |
20726 if (!ctx || !ctx->current || !ctx->current->layout) | |
20727 return 0; | |
20728 | |
20729 win = ctx->current; | |
20730 layout = win->layout; | |
20731 | |
20732 state = nk_widget(&bounds, ctx); | |
20733 if (!state) return 0; | |
20734 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20735 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, | |
20736 img, ctx->button_behavior, style, in); | |
20737 } | |
20738 | |
20739 NK_API int | |
20740 nk_button_image(struct nk_context *ctx, struct nk_image img) | |
20741 { | |
20742 NK_ASSERT(ctx); | |
20743 if (!ctx) return 0; | |
20744 return nk_button_image_styled(ctx, &ctx->style.button, img); | |
20745 } | |
20746 | |
20747 NK_API int | |
20748 nk_button_symbol_text_styled(struct nk_context *ctx, | |
20749 const struct nk_style_button *style, enum nk_symbol_type symbol, | |
20750 const char *text, int len, nk_flags align) | |
20751 { | |
20752 struct nk_window *win; | |
20753 struct nk_panel *layout; | |
20754 const struct nk_input *in; | |
20755 | |
20756 struct nk_rect bounds; | |
20757 enum nk_widget_layout_states state; | |
20758 | |
20759 NK_ASSERT(ctx); | |
20760 NK_ASSERT(ctx->current); | |
20761 NK_ASSERT(ctx->current->layout); | |
20762 if (!ctx || !ctx->current || !ctx->current->layout) | |
20763 return 0; | |
20764 | |
20765 win = ctx->current; | |
20766 layout = win->layout; | |
20767 | |
20768 state = nk_widget(&bounds, ctx); | |
20769 if (!state) return 0; | |
20770 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20771 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, | |
20772 symbol, text, len, align, ctx->button_behavior, | |
20773 style, ctx->style.font, in); | |
20774 } | |
20775 | |
20776 NK_API int | |
20777 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, | |
20778 const char* text, int len, nk_flags align) | |
20779 { | |
20780 NK_ASSERT(ctx); | |
20781 if (!ctx) return 0; | |
20782 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); | |
20783 } | |
20784 | |
20785 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, | |
20786 const char *label, nk_flags align) | |
20787 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);} | |
20788 | |
20789 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, | |
20790 const struct nk_style_button *style, enum nk_symbol_type symbol, | |
20791 const char *title, nk_flags align) | |
20792 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);} | |
20793 | |
20794 NK_API int | |
20795 nk_button_image_text_styled(struct nk_context *ctx, | |
20796 const struct nk_style_button *style, struct nk_image img, const char *text, | |
20797 int len, nk_flags align) | |
20798 { | |
20799 struct nk_window *win; | |
20800 struct nk_panel *layout; | |
20801 const struct nk_input *in; | |
20802 | |
20803 struct nk_rect bounds; | |
20804 enum nk_widget_layout_states state; | |
20805 | |
20806 NK_ASSERT(ctx); | |
20807 NK_ASSERT(ctx->current); | |
20808 NK_ASSERT(ctx->current->layout); | |
20809 if (!ctx || !ctx->current || !ctx->current->layout) | |
20810 return 0; | |
20811 | |
20812 win = ctx->current; | |
20813 layout = win->layout; | |
20814 | |
20815 state = nk_widget(&bounds, ctx); | |
20816 if (!state) return 0; | |
20817 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20818 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, | |
20819 bounds, img, text, len, align, ctx->button_behavior, | |
20820 style, ctx->style.font, in); | |
20821 } | |
20822 | |
20823 NK_API int | |
20824 nk_button_image_text(struct nk_context *ctx, struct nk_image img, | |
20825 const char *text, int len, nk_flags align) | |
20826 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);} | |
20827 | |
20828 | |
20829 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img, | |
20830 const char *label, nk_flags align) | |
20831 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);} | |
20832 | |
20833 NK_API int nk_button_image_label_styled(struct nk_context *ctx, | |
20834 const struct nk_style_button *style, struct nk_image img, | |
20835 const char *label, nk_flags text_alignment) | |
20836 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);} | |
20837 | |
20838 /*---------------------------------------------------------------- | |
20839 * | |
20840 * SELECTABLE | |
20841 * | |
20842 * --------------------------------------------------------------*/ | |
20843 NK_API int | |
20844 nk_selectable_text(struct nk_context *ctx, const char *str, int len, | |
20845 nk_flags align, int *value) | |
20846 { | |
20847 struct nk_window *win; | |
20848 struct nk_panel *layout; | |
20849 const struct nk_input *in; | |
20850 const struct nk_style *style; | |
20851 | |
20852 enum nk_widget_layout_states state; | |
20853 struct nk_rect bounds; | |
20854 | |
20855 NK_ASSERT(ctx); | |
20856 NK_ASSERT(value); | |
20857 NK_ASSERT(ctx->current); | |
20858 NK_ASSERT(ctx->current->layout); | |
20859 if (!ctx || !ctx->current || !ctx->current->layout || !value) | |
20860 return 0; | |
20861 | |
20862 win = ctx->current; | |
20863 layout = win->layout; | |
20864 style = &ctx->style; | |
20865 | |
20866 state = nk_widget(&bounds, ctx); | |
20867 if (!state) return 0; | |
20868 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20869 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, | |
20870 str, len, align, value, &style->selectable, in, style->font); | |
20871 } | |
20872 | |
20873 NK_API int | |
20874 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, | |
20875 const char *str, int len, nk_flags align, int *value) | |
20876 { | |
20877 struct nk_window *win; | |
20878 struct nk_panel *layout; | |
20879 const struct nk_input *in; | |
20880 const struct nk_style *style; | |
20881 | |
20882 enum nk_widget_layout_states state; | |
20883 struct nk_rect bounds; | |
20884 | |
20885 NK_ASSERT(ctx); | |
20886 NK_ASSERT(value); | |
20887 NK_ASSERT(ctx->current); | |
20888 NK_ASSERT(ctx->current->layout); | |
20889 if (!ctx || !ctx->current || !ctx->current->layout || !value) | |
20890 return 0; | |
20891 | |
20892 win = ctx->current; | |
20893 layout = win->layout; | |
20894 style = &ctx->style; | |
20895 | |
20896 state = nk_widget(&bounds, ctx); | |
20897 if (!state) return 0; | |
20898 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20899 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, | |
20900 str, len, align, value, &img, &style->selectable, in, style->font); | |
20901 } | |
20902 | |
20903 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len, | |
20904 nk_flags align, int value) | |
20905 {nk_selectable_text(ctx, str, len, align, &value);return value;} | |
20906 | |
20907 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value) | |
20908 {return nk_selectable_text(ctx, str, nk_strlen(str), align, value);} | |
20909 | |
20910 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, | |
20911 const char *str, nk_flags align, int *value) | |
20912 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);} | |
20913 | |
20914 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value) | |
20915 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;} | |
20916 | |
20917 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img, | |
20918 const char *str, nk_flags align, int value) | |
20919 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;} | |
20920 | |
20921 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img, | |
20922 const char *str, int len, nk_flags align, int value) | |
20923 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;} | |
20924 | |
20925 /*---------------------------------------------------------------- | |
20926 * | |
20927 * CHECKBOX | |
20928 * | |
20929 * --------------------------------------------------------------*/ | |
20930 NK_API int | |
20931 nk_check_text(struct nk_context *ctx, const char *text, int len, int active) | |
20932 { | |
20933 struct nk_window *win; | |
20934 struct nk_panel *layout; | |
20935 const struct nk_input *in; | |
20936 const struct nk_style *style; | |
20937 | |
20938 struct nk_rect bounds; | |
20939 enum nk_widget_layout_states state; | |
20940 | |
20941 NK_ASSERT(ctx); | |
20942 NK_ASSERT(ctx->current); | |
20943 NK_ASSERT(ctx->current->layout); | |
20944 if (!ctx || !ctx->current || !ctx->current->layout) | |
20945 return active; | |
20946 | |
20947 win = ctx->current; | |
20948 style = &ctx->style; | |
20949 layout = win->layout; | |
20950 | |
20951 state = nk_widget(&bounds, ctx); | |
20952 if (!state) return active; | |
20953 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
20954 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, | |
20955 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); | |
20956 return active; | |
20957 } | |
20958 | |
20959 NK_API unsigned int | |
20960 nk_check_flags_text(struct nk_context *ctx, const char *text, int len, | |
20961 unsigned int flags, unsigned int value) | |
20962 { | |
20963 int old_active; | |
20964 NK_ASSERT(ctx); | |
20965 NK_ASSERT(text); | |
20966 if (!ctx || !text) return flags; | |
20967 old_active = (int)((flags & value) & value); | |
20968 if (nk_check_text(ctx, text, len, old_active)) | |
20969 flags |= value; | |
20970 else flags &= ~value; | |
20971 return flags; | |
20972 } | |
20973 | |
20974 NK_API int | |
20975 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active) | |
20976 { | |
20977 int old_val; | |
20978 NK_ASSERT(ctx); | |
20979 NK_ASSERT(text); | |
20980 NK_ASSERT(active); | |
20981 if (!ctx || !text || !active) return 0; | |
20982 old_val = *active; | |
20983 *active = nk_check_text(ctx, text, len, *active); | |
20984 return old_val != *active; | |
20985 } | |
20986 | |
20987 NK_API int | |
20988 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, | |
20989 unsigned int *flags, unsigned int value) | |
20990 { | |
20991 int active; | |
20992 NK_ASSERT(ctx); | |
20993 NK_ASSERT(text); | |
20994 NK_ASSERT(flags); | |
20995 if (!ctx || !text || !flags) return 0; | |
20996 | |
20997 active = (int)((*flags & value) & value); | |
20998 if (nk_checkbox_text(ctx, text, len, &active)) { | |
20999 if (active) *flags |= value; | |
21000 else *flags &= ~value; | |
21001 return 1; | |
21002 } | |
21003 return 0; | |
21004 } | |
21005 | |
21006 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active) | |
21007 {return nk_check_text(ctx, label, nk_strlen(label), active);} | |
21008 | |
21009 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, | |
21010 unsigned int flags, unsigned int value) | |
21011 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);} | |
21012 | |
21013 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active) | |
21014 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);} | |
21015 | |
21016 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label, | |
21017 unsigned int *flags, unsigned int value) | |
21018 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);} | |
21019 | |
21020 /*---------------------------------------------------------------- | |
21021 * | |
21022 * OPTION | |
21023 * | |
21024 * --------------------------------------------------------------*/ | |
21025 NK_API int | |
21026 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active) | |
21027 { | |
21028 struct nk_window *win; | |
21029 struct nk_panel *layout; | |
21030 const struct nk_input *in; | |
21031 const struct nk_style *style; | |
21032 | |
21033 struct nk_rect bounds; | |
21034 enum nk_widget_layout_states state; | |
21035 | |
21036 NK_ASSERT(ctx); | |
21037 NK_ASSERT(ctx->current); | |
21038 NK_ASSERT(ctx->current->layout); | |
21039 if (!ctx || !ctx->current || !ctx->current->layout) | |
21040 return is_active; | |
21041 | |
21042 win = ctx->current; | |
21043 style = &ctx->style; | |
21044 layout = win->layout; | |
21045 | |
21046 state = nk_widget(&bounds, ctx); | |
21047 if (!state) return state; | |
21048 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21049 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, | |
21050 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); | |
21051 return is_active; | |
21052 } | |
21053 | |
21054 NK_API int | |
21055 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active) | |
21056 { | |
21057 int old_value; | |
21058 NK_ASSERT(ctx); | |
21059 NK_ASSERT(text); | |
21060 NK_ASSERT(active); | |
21061 if (!ctx || !text || !active) return 0; | |
21062 old_value = *active; | |
21063 *active = nk_option_text(ctx, text, len, old_value); | |
21064 return old_value != *active; | |
21065 } | |
21066 | |
21067 NK_API int | |
21068 nk_option_label(struct nk_context *ctx, const char *label, int active) | |
21069 {return nk_option_text(ctx, label, nk_strlen(label), active);} | |
21070 | |
21071 NK_API int | |
21072 nk_radio_label(struct nk_context *ctx, const char *label, int *active) | |
21073 {return nk_radio_text(ctx, label, nk_strlen(label), active);} | |
21074 | |
21075 /*---------------------------------------------------------------- | |
21076 * | |
21077 * SLIDER | |
21078 * | |
21079 * --------------------------------------------------------------*/ | |
21080 NK_API int | |
21081 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, | |
21082 float value_step) | |
21083 { | |
21084 struct nk_window *win; | |
21085 struct nk_panel *layout; | |
21086 struct nk_input *in; | |
21087 const struct nk_style *style; | |
21088 | |
21089 int ret = 0; | |
21090 float old_value; | |
21091 struct nk_rect bounds; | |
21092 enum nk_widget_layout_states state; | |
21093 | |
21094 NK_ASSERT(ctx); | |
21095 NK_ASSERT(ctx->current); | |
21096 NK_ASSERT(ctx->current->layout); | |
21097 NK_ASSERT(value); | |
21098 if (!ctx || !ctx->current || !ctx->current->layout || !value) | |
21099 return ret; | |
21100 | |
21101 win = ctx->current; | |
21102 style = &ctx->style; | |
21103 layout = win->layout; | |
21104 | |
21105 state = nk_widget(&bounds, ctx); | |
21106 if (!state) return ret; | |
21107 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21108 | |
21109 old_value = *value; | |
21110 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, | |
21111 old_value, max_value, value_step, &style->slider, in, style->font); | |
21112 return (old_value > *value || old_value < *value); | |
21113 } | |
21114 | |
21115 NK_API float | |
21116 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) | |
21117 { | |
21118 nk_slider_float(ctx, min, &val, max, step); return val; | |
21119 } | |
21120 | |
21121 NK_API int | |
21122 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) | |
21123 { | |
21124 float value = (float)val; | |
21125 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); | |
21126 return (int)value; | |
21127 } | |
21128 | |
21129 NK_API int | |
21130 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) | |
21131 { | |
21132 int ret; | |
21133 float value = (float)*val; | |
21134 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); | |
21135 *val = (int)value; | |
21136 return ret; | |
21137 } | |
21138 | |
21139 /*---------------------------------------------------------------- | |
21140 * | |
21141 * PROGRESSBAR | |
21142 * | |
21143 * --------------------------------------------------------------*/ | |
21144 NK_API int | |
21145 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable) | |
21146 { | |
21147 struct nk_window *win; | |
21148 struct nk_panel *layout; | |
21149 const struct nk_style *style; | |
21150 const struct nk_input *in; | |
21151 | |
21152 struct nk_rect bounds; | |
21153 enum nk_widget_layout_states state; | |
21154 nk_size old_value; | |
21155 | |
21156 NK_ASSERT(ctx); | |
21157 NK_ASSERT(cur); | |
21158 NK_ASSERT(ctx->current); | |
21159 NK_ASSERT(ctx->current->layout); | |
21160 if (!ctx || !ctx->current || !ctx->current->layout || !cur) | |
21161 return 0; | |
21162 | |
21163 win = ctx->current; | |
21164 style = &ctx->style; | |
21165 layout = win->layout; | |
21166 state = nk_widget(&bounds, ctx); | |
21167 if (!state) return 0; | |
21168 | |
21169 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21170 old_value = *cur; | |
21171 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, | |
21172 *cur, max, is_modifyable, &style->progress, in); | |
21173 return (*cur != old_value); | |
21174 } | |
21175 | |
21176 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable) | |
21177 {nk_progress(ctx, &cur, max, modifyable);return cur;} | |
21178 | |
21179 /*---------------------------------------------------------------- | |
21180 * | |
21181 * EDIT | |
21182 * | |
21183 * --------------------------------------------------------------*/ | |
21184 NK_API void | |
21185 nk_edit_focus(struct nk_context *ctx, nk_flags flags) | |
21186 { | |
21187 nk_hash hash; | |
21188 struct nk_window *win; | |
21189 | |
21190 NK_ASSERT(ctx); | |
21191 NK_ASSERT(ctx->current); | |
21192 if (!ctx || !ctx->current) return; | |
21193 | |
21194 win = ctx->current; | |
21195 hash = win->edit.seq; | |
21196 win->edit.active = nk_true; | |
21197 win->edit.name = hash; | |
21198 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) | |
21199 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; | |
21200 } | |
21201 | |
21202 NK_API void | |
21203 nk_edit_unfocus(struct nk_context *ctx) | |
21204 { | |
21205 struct nk_window *win; | |
21206 NK_ASSERT(ctx); | |
21207 NK_ASSERT(ctx->current); | |
21208 if (!ctx || !ctx->current) return; | |
21209 | |
21210 win = ctx->current; | |
21211 win->edit.active = nk_false; | |
21212 win->edit.name = 0; | |
21213 } | |
21214 | |
21215 NK_API nk_flags | |
21216 nk_edit_string(struct nk_context *ctx, nk_flags flags, | |
21217 char *memory, int *len, int max, nk_plugin_filter filter) | |
21218 { | |
21219 nk_hash hash; | |
21220 nk_flags state; | |
21221 struct nk_text_edit *edit; | |
21222 struct nk_window *win; | |
21223 | |
21224 NK_ASSERT(ctx); | |
21225 NK_ASSERT(memory); | |
21226 NK_ASSERT(len); | |
21227 if (!ctx || !memory || !len) | |
21228 return 0; | |
21229 | |
21230 filter = (!filter) ? nk_filter_default: filter; | |
21231 win = ctx->current; | |
21232 hash = win->edit.seq; | |
21233 edit = &ctx->text_edit; | |
21234 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? | |
21235 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); | |
21236 | |
21237 if (win->edit.active && hash == win->edit.name) { | |
21238 if (flags & NK_EDIT_NO_CURSOR) | |
21239 edit->cursor = nk_utf_len(memory, *len); | |
21240 else edit->cursor = win->edit.cursor; | |
21241 if (!(flags & NK_EDIT_SELECTABLE)) { | |
21242 edit->select_start = win->edit.cursor; | |
21243 edit->select_end = win->edit.cursor; | |
21244 } else { | |
21245 edit->select_start = win->edit.sel_start; | |
21246 edit->select_end = win->edit.sel_end; | |
21247 } | |
21248 edit->mode = win->edit.mode; | |
21249 edit->scrollbar.x = (float)win->edit.scrollbar.x; | |
21250 edit->scrollbar.y = (float)win->edit.scrollbar.y; | |
21251 edit->active = nk_true; | |
21252 } else edit->active = nk_false; | |
21253 | |
21254 max = NK_MAX(1, max); | |
21255 *len = NK_MIN(*len, max-1); | |
21256 nk_str_init_fixed(&edit->string, memory, (nk_size)max); | |
21257 edit->string.buffer.allocated = (nk_size)*len; | |
21258 edit->string.len = nk_utf_len(memory, *len); | |
21259 state = nk_edit_buffer(ctx, flags, edit, filter); | |
21260 *len = (int)edit->string.buffer.allocated; | |
21261 | |
21262 if (edit->active) { | |
21263 win->edit.cursor = edit->cursor; | |
21264 win->edit.sel_start = edit->select_start; | |
21265 win->edit.sel_end = edit->select_end; | |
21266 win->edit.mode = edit->mode; | |
21267 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x; | |
21268 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y; | |
21269 } | |
21270 return state; | |
21271 } | |
21272 | |
21273 NK_API nk_flags | |
21274 nk_edit_buffer(struct nk_context *ctx, nk_flags flags, | |
21275 struct nk_text_edit *edit, nk_plugin_filter filter) | |
21276 { | |
21277 struct nk_window *win; | |
21278 struct nk_style *style; | |
21279 struct nk_input *in; | |
21280 | |
21281 enum nk_widget_layout_states state; | |
21282 struct nk_rect bounds; | |
21283 | |
21284 nk_flags ret_flags = 0; | |
21285 unsigned char prev_state; | |
21286 nk_hash hash; | |
21287 | |
21288 /* make sure correct values */ | |
21289 NK_ASSERT(ctx); | |
21290 NK_ASSERT(edit); | |
21291 NK_ASSERT(ctx->current); | |
21292 NK_ASSERT(ctx->current->layout); | |
21293 if (!ctx || !ctx->current || !ctx->current->layout) | |
21294 return 0; | |
21295 | |
21296 win = ctx->current; | |
21297 style = &ctx->style; | |
21298 state = nk_widget(&bounds, ctx); | |
21299 if (!state) return state; | |
21300 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21301 | |
21302 /* check if edit is currently hot item */ | |
21303 hash = win->edit.seq++; | |
21304 if (win->edit.active && hash == win->edit.name) { | |
21305 if (flags & NK_EDIT_NO_CURSOR) | |
21306 edit->cursor = edit->string.len; | |
21307 if (!(flags & NK_EDIT_SELECTABLE)) { | |
21308 edit->select_start = edit->cursor; | |
21309 edit->select_end = edit->cursor; | |
21310 } | |
21311 if (flags & NK_EDIT_CLIPBOARD) | |
21312 edit->clip = ctx->clip; | |
21313 edit->active = win->edit.active; | |
21314 } else edit->active = nk_false; | |
21315 edit->mode = win->edit.mode; | |
21316 | |
21317 filter = (!filter) ? nk_filter_default: filter; | |
21318 prev_state = (unsigned char)edit->active; | |
21319 in = (flags & NK_EDIT_READ_ONLY) ? 0: in; | |
21320 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, | |
21321 filter, edit, &style->edit, in, style->font); | |
21322 | |
21323 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
21324 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; | |
21325 if (edit->active && prev_state != edit->active) { | |
21326 /* current edit is now hot */ | |
21327 win->edit.active = nk_true; | |
21328 win->edit.name = hash; | |
21329 } else if (prev_state && !edit->active) { | |
21330 /* current edit is now cold */ | |
21331 win->edit.active = nk_false; | |
21332 } | |
21333 return ret_flags; | |
21334 } | |
21335 | |
21336 NK_API nk_flags | |
21337 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, | |
21338 char *buffer, int max, nk_plugin_filter filter) | |
21339 { | |
21340 nk_flags result; | |
21341 int len = nk_strlen(buffer); | |
21342 result = nk_edit_string(ctx, flags, buffer, &len, max, filter); | |
21343 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; | |
21344 return result; | |
21345 } | |
21346 | |
21347 /*---------------------------------------------------------------- | |
21348 * | |
21349 * PROPERTY | |
21350 * | |
21351 * --------------------------------------------------------------*/ | |
21352 NK_INTERN struct nk_property_variant | |
21353 nk_property_variant_int(int value, int min_value, int max_value, int step) | |
21354 { | |
21355 struct nk_property_variant result; | |
21356 result.kind = NK_PROPERTY_INT; | |
21357 result.value.i = value; | |
21358 result.min_value.i = min_value; | |
21359 result.max_value.i = max_value; | |
21360 result.step.i = step; | |
21361 return result; | |
21362 } | |
21363 | |
21364 NK_INTERN struct nk_property_variant | |
21365 nk_property_variant_float(float value, float min_value, float max_value, float step) | |
21366 { | |
21367 struct nk_property_variant result; | |
21368 result.kind = NK_PROPERTY_FLOAT; | |
21369 result.value.f = value; | |
21370 result.min_value.f = min_value; | |
21371 result.max_value.f = max_value; | |
21372 result.step.f = step; | |
21373 return result; | |
21374 } | |
21375 | |
21376 NK_INTERN struct nk_property_variant | |
21377 nk_property_variant_double(double value, double min_value, double max_value, | |
21378 double step) | |
21379 { | |
21380 struct nk_property_variant result; | |
21381 result.kind = NK_PROPERTY_DOUBLE; | |
21382 result.value.d = value; | |
21383 result.min_value.d = min_value; | |
21384 result.max_value.d = max_value; | |
21385 result.step.d = step; | |
21386 return result; | |
21387 } | |
21388 | |
21389 NK_INTERN void | |
21390 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, | |
21391 float inc_per_pixel, const enum nk_property_filter filter) | |
21392 { | |
21393 struct nk_window *win; | |
21394 struct nk_panel *layout; | |
21395 struct nk_input *in; | |
21396 const struct nk_style *style; | |
21397 | |
21398 struct nk_rect bounds; | |
21399 enum nk_widget_layout_states s; | |
21400 | |
21401 int *state = 0; | |
21402 nk_hash hash = 0; | |
21403 char *buffer = 0; | |
21404 int *len = 0; | |
21405 int *cursor = 0; | |
21406 int *select_begin = 0; | |
21407 int *select_end = 0; | |
21408 int old_state; | |
21409 | |
21410 char dummy_buffer[NK_MAX_NUMBER_BUFFER]; | |
21411 int dummy_state = NK_PROPERTY_DEFAULT; | |
21412 int dummy_length = 0; | |
21413 int dummy_cursor = 0; | |
21414 int dummy_select_begin = 0; | |
21415 int dummy_select_end = 0; | |
21416 | |
21417 NK_ASSERT(ctx); | |
21418 NK_ASSERT(ctx->current); | |
21419 NK_ASSERT(ctx->current->layout); | |
21420 if (!ctx || !ctx->current || !ctx->current->layout) | |
21421 return; | |
21422 | |
21423 win = ctx->current; | |
21424 layout = win->layout; | |
21425 style = &ctx->style; | |
21426 s = nk_widget(&bounds, ctx); | |
21427 if (!s) return; | |
21428 | |
21429 /* calculate hash from name */ | |
21430 if (name[0] == '#') { | |
21431 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); | |
21432 name++; /* special number hash */ | |
21433 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); | |
21434 | |
21435 /* check if property is currently hot item */ | |
21436 if (win->property.active && hash == win->property.name) { | |
21437 buffer = win->property.buffer; | |
21438 len = &win->property.length; | |
21439 cursor = &win->property.cursor; | |
21440 state = &win->property.state; | |
21441 select_begin = &win->property.select_start; | |
21442 select_end = &win->property.select_end; | |
21443 } else { | |
21444 buffer = dummy_buffer; | |
21445 len = &dummy_length; | |
21446 cursor = &dummy_cursor; | |
21447 state = &dummy_state; | |
21448 select_begin = &dummy_select_begin; | |
21449 select_end = &dummy_select_end; | |
21450 } | |
21451 | |
21452 /* execute property widget */ | |
21453 old_state = *state; | |
21454 ctx->text_edit.clip = ctx->clip; | |
21455 in = ((s == NK_WIDGET_ROM && !win->property.active) || | |
21456 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21457 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, | |
21458 variant, inc_per_pixel, buffer, len, state, cursor, select_begin, | |
21459 select_end, &style->property, filter, in, style->font, &ctx->text_edit, | |
21460 ctx->button_behavior); | |
21461 | |
21462 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { | |
21463 /* current property is now hot */ | |
21464 win->property.active = 1; | |
21465 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); | |
21466 win->property.length = *len; | |
21467 win->property.cursor = *cursor; | |
21468 win->property.state = *state; | |
21469 win->property.name = hash; | |
21470 win->property.select_start = *select_begin; | |
21471 win->property.select_end = *select_end; | |
21472 if (*state == NK_PROPERTY_DRAG) { | |
21473 ctx->input.mouse.grab = nk_true; | |
21474 ctx->input.mouse.grabbed = nk_true; | |
21475 } | |
21476 } | |
21477 /* check if previously active property is now inactive */ | |
21478 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { | |
21479 if (old_state == NK_PROPERTY_DRAG) { | |
21480 ctx->input.mouse.grab = nk_false; | |
21481 ctx->input.mouse.grabbed = nk_false; | |
21482 ctx->input.mouse.ungrab = nk_true; | |
21483 } | |
21484 win->property.select_start = 0; | |
21485 win->property.select_end = 0; | |
21486 win->property.active = 0; | |
21487 } | |
21488 } | |
21489 | |
21490 NK_API void | |
21491 nk_property_int(struct nk_context *ctx, const char *name, | |
21492 int min, int *val, int max, int step, float inc_per_pixel) | |
21493 { | |
21494 struct nk_property_variant variant; | |
21495 NK_ASSERT(ctx); | |
21496 NK_ASSERT(name); | |
21497 NK_ASSERT(val); | |
21498 | |
21499 if (!ctx || !ctx->current || !name || !val) return; | |
21500 variant = nk_property_variant_int(*val, min, max, step); | |
21501 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); | |
21502 *val = variant.value.i; | |
21503 } | |
21504 | |
21505 NK_API void | |
21506 nk_property_float(struct nk_context *ctx, const char *name, | |
21507 float min, float *val, float max, float step, float inc_per_pixel) | |
21508 { | |
21509 struct nk_property_variant variant; | |
21510 NK_ASSERT(ctx); | |
21511 NK_ASSERT(name); | |
21512 NK_ASSERT(val); | |
21513 | |
21514 if (!ctx || !ctx->current || !name || !val) return; | |
21515 variant = nk_property_variant_float(*val, min, max, step); | |
21516 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); | |
21517 *val = variant.value.f; | |
21518 } | |
21519 | |
21520 NK_API void | |
21521 nk_property_double(struct nk_context *ctx, const char *name, | |
21522 double min, double *val, double max, double step, float inc_per_pixel) | |
21523 { | |
21524 struct nk_property_variant variant; | |
21525 NK_ASSERT(ctx); | |
21526 NK_ASSERT(name); | |
21527 NK_ASSERT(val); | |
21528 | |
21529 if (!ctx || !ctx->current || !name || !val) return; | |
21530 variant = nk_property_variant_double(*val, min, max, step); | |
21531 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); | |
21532 *val = variant.value.d; | |
21533 } | |
21534 | |
21535 NK_API int | |
21536 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, | |
21537 int max, int step, float inc_per_pixel) | |
21538 { | |
21539 struct nk_property_variant variant; | |
21540 NK_ASSERT(ctx); | |
21541 NK_ASSERT(name); | |
21542 | |
21543 if (!ctx || !ctx->current || !name) return val; | |
21544 variant = nk_property_variant_int(val, min, max, step); | |
21545 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); | |
21546 val = variant.value.i; | |
21547 return val; | |
21548 } | |
21549 | |
21550 NK_API float | |
21551 nk_propertyf(struct nk_context *ctx, const char *name, float min, | |
21552 float val, float max, float step, float inc_per_pixel) | |
21553 { | |
21554 struct nk_property_variant variant; | |
21555 NK_ASSERT(ctx); | |
21556 NK_ASSERT(name); | |
21557 | |
21558 if (!ctx || !ctx->current || !name) return val; | |
21559 variant = nk_property_variant_float(val, min, max, step); | |
21560 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); | |
21561 val = variant.value.f; | |
21562 return val; | |
21563 } | |
21564 | |
21565 NK_API double | |
21566 nk_propertyd(struct nk_context *ctx, const char *name, double min, | |
21567 double val, double max, double step, float inc_per_pixel) | |
21568 { | |
21569 struct nk_property_variant variant; | |
21570 NK_ASSERT(ctx); | |
21571 NK_ASSERT(name); | |
21572 | |
21573 if (!ctx || !ctx->current || !name) return val; | |
21574 variant = nk_property_variant_double(val, min, max, step); | |
21575 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); | |
21576 val = variant.value.d; | |
21577 return val; | |
21578 } | |
21579 | |
21580 /*---------------------------------------------------------------- | |
21581 * | |
21582 * COLOR PICKER | |
21583 * | |
21584 * --------------------------------------------------------------*/ | |
21585 NK_API int | |
21586 nk_color_pick(struct nk_context * ctx, struct nk_color *color, | |
21587 enum nk_color_format fmt) | |
21588 { | |
21589 struct nk_window *win; | |
21590 struct nk_panel *layout; | |
21591 const struct nk_style *config; | |
21592 const struct nk_input *in; | |
21593 | |
21594 enum nk_widget_layout_states state; | |
21595 struct nk_rect bounds; | |
21596 | |
21597 NK_ASSERT(ctx); | |
21598 NK_ASSERT(color); | |
21599 NK_ASSERT(ctx->current); | |
21600 NK_ASSERT(ctx->current->layout); | |
21601 if (!ctx || !ctx->current || !ctx->current->layout || !color) | |
21602 return 0; | |
21603 | |
21604 win = ctx->current; | |
21605 config = &ctx->style; | |
21606 layout = win->layout; | |
21607 state = nk_widget(&bounds, ctx); | |
21608 if (!state) return 0; | |
21609 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
21610 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, | |
21611 nk_vec2(0,0), in, config->font); | |
21612 } | |
21613 | |
21614 NK_API struct nk_color | |
21615 nk_color_picker(struct nk_context *ctx, struct nk_color color, | |
21616 enum nk_color_format fmt) | |
21617 { | |
21618 nk_color_pick(ctx, &color, fmt); | |
21619 return color; | |
21620 } | |
21621 | |
21622 /* ------------------------------------------------------------- | |
21623 * | |
21624 * CHART | |
21625 * | |
21626 * --------------------------------------------------------------*/ | |
21627 NK_API int | |
21628 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, | |
21629 struct nk_color color, struct nk_color highlight, | |
21630 int count, float min_value, float max_value) | |
21631 { | |
21632 struct nk_window *win; | |
21633 struct nk_chart *chart; | |
21634 const struct nk_style *config; | |
21635 const struct nk_style_chart *style; | |
21636 | |
21637 const struct nk_style_item *background; | |
21638 struct nk_rect bounds = {0, 0, 0, 0}; | |
21639 | |
21640 NK_ASSERT(ctx); | |
21641 NK_ASSERT(ctx->current); | |
21642 NK_ASSERT(ctx->current->layout); | |
21643 | |
21644 if (!ctx || !ctx->current || !ctx->current->layout) return 0; | |
21645 if (!nk_widget(&bounds, ctx)) { | |
21646 chart = &ctx->current->layout->chart; | |
21647 nk_zero(chart, sizeof(*chart)); | |
21648 return 0; | |
21649 } | |
21650 | |
21651 win = ctx->current; | |
21652 config = &ctx->style; | |
21653 chart = &win->layout->chart; | |
21654 style = &config->chart; | |
21655 | |
21656 /* setup basic generic chart */ | |
21657 nk_zero(chart, sizeof(*chart)); | |
21658 chart->x = bounds.x + style->padding.x; | |
21659 chart->y = bounds.y + style->padding.y; | |
21660 chart->w = bounds.w - 2 * style->padding.x; | |
21661 chart->h = bounds.h - 2 * style->padding.y; | |
21662 chart->w = NK_MAX(chart->w, 2 * style->padding.x); | |
21663 chart->h = NK_MAX(chart->h, 2 * style->padding.y); | |
21664 | |
21665 /* add first slot into chart */ | |
21666 {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; | |
21667 slot->type = type; | |
21668 slot->count = count; | |
21669 slot->color = color; | |
21670 slot->highlight = highlight; | |
21671 slot->min = NK_MIN(min_value, max_value); | |
21672 slot->max = NK_MAX(min_value, max_value); | |
21673 slot->range = slot->max - slot->min;} | |
21674 | |
21675 /* draw chart background */ | |
21676 background = &style->background; | |
21677 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
21678 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); | |
21679 } else { | |
21680 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); | |
21681 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), | |
21682 style->rounding, style->background.data.color); | |
21683 } | |
21684 return 1; | |
21685 } | |
21686 | |
21687 NK_API int | |
21688 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, | |
21689 int count, float min_value, float max_value) | |
21690 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);} | |
21691 | |
21692 NK_API void | |
21693 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, | |
21694 struct nk_color color, struct nk_color highlight, | |
21695 int count, float min_value, float max_value) | |
21696 { | |
21697 NK_ASSERT(ctx); | |
21698 NK_ASSERT(ctx->current); | |
21699 NK_ASSERT(ctx->current->layout); | |
21700 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); | |
21701 if (!ctx || !ctx->current || !ctx->current->layout) return; | |
21702 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; | |
21703 | |
21704 /* add another slot into the graph */ | |
21705 {struct nk_chart *chart = &ctx->current->layout->chart; | |
21706 struct nk_chart_slot *slot = &chart->slots[chart->slot++]; | |
21707 slot->type = type; | |
21708 slot->count = count; | |
21709 slot->color = color; | |
21710 slot->highlight = highlight; | |
21711 slot->min = NK_MIN(min_value, max_value); | |
21712 slot->max = NK_MAX(min_value, max_value); | |
21713 slot->range = slot->max - slot->min;} | |
21714 } | |
21715 | |
21716 NK_API void | |
21717 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, | |
21718 int count, float min_value, float max_value) | |
21719 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);} | |
21720 | |
21721 NK_INTERN nk_flags | |
21722 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, | |
21723 struct nk_chart *g, float value, int slot) | |
21724 { | |
21725 struct nk_panel *layout = win->layout; | |
21726 const struct nk_input *i = &ctx->input; | |
21727 struct nk_command_buffer *out = &win->buffer; | |
21728 | |
21729 nk_flags ret = 0; | |
21730 struct nk_vec2 cur; | |
21731 struct nk_rect bounds; | |
21732 struct nk_color color; | |
21733 float step; | |
21734 float range; | |
21735 float ratio; | |
21736 | |
21737 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); | |
21738 step = g->w / (float)g->slots[slot].count; | |
21739 range = g->slots[slot].max - g->slots[slot].min; | |
21740 ratio = (value - g->slots[slot].min) / range; | |
21741 | |
21742 if (g->slots[slot].index == 0) { | |
21743 /* first data point does not have a connection */ | |
21744 g->slots[slot].last.x = g->x; | |
21745 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; | |
21746 | |
21747 bounds.x = g->slots[slot].last.x - 2; | |
21748 bounds.y = g->slots[slot].last.y - 2; | |
21749 bounds.w = bounds.h = 4; | |
21750 | |
21751 color = g->slots[slot].color; | |
21752 if (!(layout->flags & NK_WINDOW_ROM) && | |
21753 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ | |
21754 ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; | |
21755 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && | |
21756 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; | |
21757 color = g->slots[slot].highlight; | |
21758 } | |
21759 nk_fill_rect(out, bounds, 0, color); | |
21760 g->slots[slot].index += 1; | |
21761 return ret; | |
21762 } | |
21763 | |
21764 /* draw a line between the last data point and the new one */ | |
21765 color = g->slots[slot].color; | |
21766 cur.x = g->x + (float)(step * (float)g->slots[slot].index); | |
21767 cur.y = (g->y + g->h) - (ratio * (float)g->h); | |
21768 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); | |
21769 | |
21770 bounds.x = cur.x - 3; | |
21771 bounds.y = cur.y - 3; | |
21772 bounds.w = bounds.h = 6; | |
21773 | |
21774 /* user selection of current data point */ | |
21775 if (!(layout->flags & NK_WINDOW_ROM)) { | |
21776 if (nk_input_is_mouse_hovering_rect(i, bounds)) { | |
21777 ret = NK_CHART_HOVERING; | |
21778 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && | |
21779 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; | |
21780 color = g->slots[slot].highlight; | |
21781 } | |
21782 } | |
21783 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); | |
21784 | |
21785 /* save current data point position */ | |
21786 g->slots[slot].last.x = cur.x; | |
21787 g->slots[slot].last.y = cur.y; | |
21788 g->slots[slot].index += 1; | |
21789 return ret; | |
21790 } | |
21791 | |
21792 NK_INTERN nk_flags | |
21793 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, | |
21794 struct nk_chart *chart, float value, int slot) | |
21795 { | |
21796 struct nk_command_buffer *out = &win->buffer; | |
21797 const struct nk_input *in = &ctx->input; | |
21798 struct nk_panel *layout = win->layout; | |
21799 | |
21800 float ratio; | |
21801 nk_flags ret = 0; | |
21802 struct nk_color color; | |
21803 struct nk_rect item = {0,0,0,0}; | |
21804 | |
21805 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); | |
21806 if (chart->slots[slot].index >= chart->slots[slot].count) | |
21807 return nk_false; | |
21808 if (chart->slots[slot].count) { | |
21809 float padding = (float)(chart->slots[slot].count-1); | |
21810 item.w = (chart->w - padding) / (float)(chart->slots[slot].count); | |
21811 } | |
21812 | |
21813 /* calculate bounds of current bar chart entry */ | |
21814 color = chart->slots[slot].color;; | |
21815 item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); | |
21816 if (value >= 0) { | |
21817 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); | |
21818 item.y = (chart->y + chart->h) - chart->h * ratio; | |
21819 } else { | |
21820 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; | |
21821 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; | |
21822 } | |
21823 item.x = chart->x + ((float)chart->slots[slot].index * item.w); | |
21824 item.x = item.x + ((float)chart->slots[slot].index); | |
21825 | |
21826 /* user chart bar selection */ | |
21827 if (!(layout->flags & NK_WINDOW_ROM) && | |
21828 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { | |
21829 ret = NK_CHART_HOVERING; | |
21830 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && | |
21831 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; | |
21832 color = chart->slots[slot].highlight; | |
21833 } | |
21834 nk_fill_rect(out, item, 0, color); | |
21835 chart->slots[slot].index += 1; | |
21836 return ret; | |
21837 } | |
21838 | |
21839 NK_API nk_flags | |
21840 nk_chart_push_slot(struct nk_context *ctx, float value, int slot) | |
21841 { | |
21842 nk_flags flags; | |
21843 struct nk_window *win; | |
21844 | |
21845 NK_ASSERT(ctx); | |
21846 NK_ASSERT(ctx->current); | |
21847 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); | |
21848 NK_ASSERT(slot < ctx->current->layout->chart.slot); | |
21849 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; | |
21850 if (slot >= ctx->current->layout->chart.slot) return nk_false; | |
21851 | |
21852 win = ctx->current; | |
21853 if (win->layout->chart.slot < slot) return nk_false; | |
21854 switch (win->layout->chart.slots[slot].type) { | |
21855 case NK_CHART_LINES: | |
21856 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; | |
21857 case NK_CHART_COLUMN: | |
21858 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; | |
21859 default: | |
21860 case NK_CHART_MAX: | |
21861 flags = 0; | |
21862 } | |
21863 return flags; | |
21864 } | |
21865 | |
21866 NK_API nk_flags | |
21867 nk_chart_push(struct nk_context *ctx, float value) | |
21868 {return nk_chart_push_slot(ctx, value, 0);} | |
21869 | |
21870 NK_API void | |
21871 nk_chart_end(struct nk_context *ctx) | |
21872 { | |
21873 struct nk_window *win; | |
21874 struct nk_chart *chart; | |
21875 | |
21876 NK_ASSERT(ctx); | |
21877 NK_ASSERT(ctx->current); | |
21878 if (!ctx || !ctx->current) | |
21879 return; | |
21880 | |
21881 win = ctx->current; | |
21882 chart = &win->layout->chart; | |
21883 NK_MEMSET(chart, 0, sizeof(*chart)); | |
21884 return; | |
21885 } | |
21886 | |
21887 NK_API void | |
21888 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, | |
21889 int count, int offset) | |
21890 { | |
21891 int i = 0; | |
21892 float min_value; | |
21893 float max_value; | |
21894 | |
21895 NK_ASSERT(ctx); | |
21896 NK_ASSERT(values); | |
21897 if (!ctx || !values || !count) return; | |
21898 | |
21899 min_value = values[offset]; | |
21900 max_value = values[offset]; | |
21901 for (i = 0; i < count; ++i) { | |
21902 min_value = NK_MIN(values[i + offset], min_value); | |
21903 max_value = NK_MAX(values[i + offset], max_value); | |
21904 } | |
21905 | |
21906 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { | |
21907 for (i = 0; i < count; ++i) | |
21908 nk_chart_push(ctx, values[i + offset]); | |
21909 nk_chart_end(ctx); | |
21910 } | |
21911 } | |
21912 | |
21913 NK_API void | |
21914 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, | |
21915 float(*value_getter)(void* user, int index), int count, int offset) | |
21916 { | |
21917 int i = 0; | |
21918 float min_value; | |
21919 float max_value; | |
21920 | |
21921 NK_ASSERT(ctx); | |
21922 NK_ASSERT(value_getter); | |
21923 if (!ctx || !value_getter || !count) return; | |
21924 | |
21925 max_value = min_value = value_getter(userdata, offset); | |
21926 for (i = 0; i < count; ++i) { | |
21927 float value = value_getter(userdata, i + offset); | |
21928 min_value = NK_MIN(value, min_value); | |
21929 max_value = NK_MAX(value, max_value); | |
21930 } | |
21931 | |
21932 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { | |
21933 for (i = 0; i < count; ++i) | |
21934 nk_chart_push(ctx, value_getter(userdata, i + offset)); | |
21935 nk_chart_end(ctx); | |
21936 } | |
21937 } | |
21938 | |
21939 /* ------------------------------------------------------------- | |
21940 * | |
21941 * GROUP | |
21942 * | |
21943 * --------------------------------------------------------------*/ | |
21944 NK_API int | |
21945 nk_group_scrolled_offset_begin(struct nk_context *ctx, | |
21946 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) | |
21947 { | |
21948 struct nk_rect bounds; | |
21949 struct nk_window panel; | |
21950 struct nk_window *win; | |
21951 | |
21952 win = ctx->current; | |
21953 nk_panel_alloc_space(&bounds, ctx); | |
21954 {const struct nk_rect *c = &win->layout->clip; | |
21955 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && | |
21956 !(flags & NK_WINDOW_MOVABLE)) { | |
21957 return 0; | |
21958 }} | |
21959 if (win->flags & NK_WINDOW_ROM) | |
21960 flags |= NK_WINDOW_ROM; | |
21961 | |
21962 /* initialize a fake window to create the panel from */ | |
21963 nk_zero(&panel, sizeof(panel)); | |
21964 panel.bounds = bounds; | |
21965 panel.flags = flags; | |
21966 panel.scrollbar.x = *x_offset; | |
21967 panel.scrollbar.y = *y_offset; | |
21968 panel.buffer = win->buffer; | |
21969 panel.layout = (struct nk_panel*)nk_create_panel(ctx); | |
21970 ctx->current = &panel; | |
21971 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); | |
21972 | |
21973 win->buffer = panel.buffer; | |
21974 win->buffer.clip = panel.layout->clip; | |
21975 panel.layout->offset_x = x_offset; | |
21976 panel.layout->offset_y = y_offset; | |
21977 panel.layout->parent = win->layout; | |
21978 win->layout = panel.layout; | |
21979 | |
21980 ctx->current = win; | |
21981 if ((panel.layout->flags & NK_WINDOW_CLOSED) || | |
21982 (panel.layout->flags & NK_WINDOW_MINIMIZED)) | |
21983 { | |
21984 nk_flags f = panel.layout->flags; | |
21985 nk_group_scrolled_end(ctx); | |
21986 if (f & NK_WINDOW_CLOSED) | |
21987 return NK_WINDOW_CLOSED; | |
21988 if (f & NK_WINDOW_MINIMIZED) | |
21989 return NK_WINDOW_MINIMIZED; | |
21990 } | |
21991 return 1; | |
21992 } | |
21993 | |
21994 NK_API void | |
21995 nk_group_scrolled_end(struct nk_context *ctx) | |
21996 { | |
21997 struct nk_window *win; | |
21998 struct nk_panel *parent; | |
21999 struct nk_panel *g; | |
22000 | |
22001 struct nk_rect clip; | |
22002 struct nk_window pan; | |
22003 struct nk_vec2 panel_padding; | |
22004 | |
22005 NK_ASSERT(ctx); | |
22006 NK_ASSERT(ctx->current); | |
22007 if (!ctx || !ctx->current) | |
22008 return; | |
22009 | |
22010 /* make sure nk_group_begin was called correctly */ | |
22011 NK_ASSERT(ctx->current); | |
22012 win = ctx->current; | |
22013 NK_ASSERT(win->layout); | |
22014 g = win->layout; | |
22015 NK_ASSERT(g->parent); | |
22016 parent = g->parent; | |
22017 | |
22018 /* dummy window */ | |
22019 nk_zero_struct(pan); | |
22020 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); | |
22021 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); | |
22022 pan.bounds.x = g->bounds.x - panel_padding.x; | |
22023 pan.bounds.w = g->bounds.w + 2 * panel_padding.x; | |
22024 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; | |
22025 if (g->flags & NK_WINDOW_BORDER) { | |
22026 pan.bounds.x -= g->border; | |
22027 pan.bounds.y -= g->border; | |
22028 pan.bounds.w += 2*g->border; | |
22029 pan.bounds.h += 2*g->border; | |
22030 } | |
22031 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { | |
22032 pan.bounds.w += ctx->style.window.scrollbar_size.x; | |
22033 pan.bounds.h += ctx->style.window.scrollbar_size.y; | |
22034 } | |
22035 pan.scrollbar.x = *g->offset_x; | |
22036 pan.scrollbar.y = *g->offset_y; | |
22037 pan.flags = g->flags; | |
22038 pan.buffer = win->buffer; | |
22039 pan.layout = g; | |
22040 pan.parent = win; | |
22041 ctx->current = &pan; | |
22042 | |
22043 /* make sure group has correct clipping rectangle */ | |
22044 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, | |
22045 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); | |
22046 nk_push_scissor(&pan.buffer, clip); | |
22047 nk_end(ctx); | |
22048 | |
22049 win->buffer = pan.buffer; | |
22050 nk_push_scissor(&win->buffer, parent->clip); | |
22051 ctx->current = win; | |
22052 win->layout = parent; | |
22053 g->bounds = pan.bounds; | |
22054 return; | |
22055 } | |
22056 | |
22057 NK_API int | |
22058 nk_group_scrolled_begin(struct nk_context *ctx, | |
22059 struct nk_scroll *scroll, const char *title, nk_flags flags) | |
22060 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);} | |
22061 | |
22062 NK_API int | |
22063 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) | |
22064 { | |
22065 int title_len; | |
22066 nk_hash title_hash; | |
22067 struct nk_window *win; | |
22068 nk_uint *x_offset; | |
22069 nk_uint *y_offset; | |
22070 | |
22071 NK_ASSERT(ctx); | |
22072 NK_ASSERT(title); | |
22073 NK_ASSERT(ctx->current); | |
22074 NK_ASSERT(ctx->current->layout); | |
22075 if (!ctx || !ctx->current || !ctx->current->layout || !title) | |
22076 return 0; | |
22077 | |
22078 /* find persistent group scrollbar value */ | |
22079 win = ctx->current; | |
22080 title_len = (int)nk_strlen(title); | |
22081 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); | |
22082 x_offset = nk_find_value(win, title_hash); | |
22083 if (!x_offset) { | |
22084 x_offset = nk_add_value(ctx, win, title_hash, 0); | |
22085 y_offset = nk_add_value(ctx, win, title_hash+1, 0); | |
22086 | |
22087 NK_ASSERT(x_offset); | |
22088 NK_ASSERT(y_offset); | |
22089 if (!x_offset || !y_offset) return 0; | |
22090 *x_offset = *y_offset = 0; | |
22091 } else y_offset = nk_find_value(win, title_hash+1); | |
22092 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); | |
22093 } | |
22094 | |
22095 NK_API void | |
22096 nk_group_end(struct nk_context *ctx) | |
22097 {nk_group_scrolled_end(ctx);} | |
22098 | |
22099 NK_API int | |
22100 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, | |
22101 const char *title, nk_flags flags, int row_height, int row_count) | |
22102 { | |
22103 int title_len; | |
22104 nk_hash title_hash; | |
22105 nk_uint *x_offset; | |
22106 nk_uint *y_offset; | |
22107 | |
22108 int result; | |
22109 struct nk_window *win; | |
22110 struct nk_panel *layout; | |
22111 const struct nk_style *style; | |
22112 struct nk_vec2 item_spacing; | |
22113 | |
22114 NK_ASSERT(ctx); | |
22115 NK_ASSERT(view); | |
22116 NK_ASSERT(title); | |
22117 if (!ctx || !view || !title) return 0; | |
22118 | |
22119 win = ctx->current; | |
22120 style = &ctx->style; | |
22121 item_spacing = style->window.spacing; | |
22122 row_height += NK_MAX(0, (int)item_spacing.y); | |
22123 | |
22124 /* find persistent list view scrollbar offset */ | |
22125 title_len = (int)nk_strlen(title); | |
22126 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); | |
22127 x_offset = nk_find_value(win, title_hash); | |
22128 if (!x_offset) { | |
22129 x_offset = nk_add_value(ctx, win, title_hash, 0); | |
22130 y_offset = nk_add_value(ctx, win, title_hash+1, 0); | |
22131 | |
22132 NK_ASSERT(x_offset); | |
22133 NK_ASSERT(y_offset); | |
22134 if (!x_offset || !y_offset) return 0; | |
22135 *x_offset = *y_offset = 0; | |
22136 } else y_offset = nk_find_value(win, title_hash+1); | |
22137 view->scroll_value = *y_offset; | |
22138 view->scroll_pointer = y_offset; | |
22139 | |
22140 *y_offset = 0; | |
22141 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); | |
22142 win = ctx->current; | |
22143 layout = win->layout; | |
22144 | |
22145 view->total_height = row_height * NK_MAX(row_count,1); | |
22146 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f); | |
22147 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0); | |
22148 view->end = view->begin + view->count; | |
22149 view->ctx = ctx; | |
22150 return result; | |
22151 } | |
22152 | |
22153 NK_API void | |
22154 nk_list_view_end(struct nk_list_view *view) | |
22155 { | |
22156 struct nk_context *ctx; | |
22157 struct nk_window *win; | |
22158 struct nk_panel *layout; | |
22159 | |
22160 NK_ASSERT(view); | |
22161 NK_ASSERT(view->ctx); | |
22162 NK_ASSERT(view->scroll_pointer); | |
22163 if (!view || !view->ctx) return; | |
22164 | |
22165 ctx = view->ctx; | |
22166 win = ctx->current; | |
22167 layout = win->layout; | |
22168 layout->at_y = layout->bounds.y + (float)view->total_height; | |
22169 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; | |
22170 nk_group_end(view->ctx); | |
22171 } | |
22172 | |
22173 /* -------------------------------------------------------------- | |
22174 * | |
22175 * POPUP | |
22176 * | |
22177 * --------------------------------------------------------------*/ | |
22178 NK_API int | |
22179 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, | |
22180 const char *title, nk_flags flags, struct nk_rect rect) | |
22181 { | |
22182 struct nk_window *popup; | |
22183 struct nk_window *win; | |
22184 struct nk_panel *panel; | |
22185 | |
22186 int title_len; | |
22187 nk_hash title_hash; | |
22188 nk_size allocated; | |
22189 | |
22190 NK_ASSERT(ctx); | |
22191 NK_ASSERT(title); | |
22192 NK_ASSERT(ctx->current); | |
22193 NK_ASSERT(ctx->current->layout); | |
22194 if (!ctx || !ctx->current || !ctx->current->layout) | |
22195 return 0; | |
22196 | |
22197 win = ctx->current; | |
22198 panel = win->layout; | |
22199 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); | |
22200 (void)panel; | |
22201 title_len = (int)nk_strlen(title); | |
22202 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); | |
22203 | |
22204 popup = win->popup.win; | |
22205 if (!popup) { | |
22206 popup = (struct nk_window*)nk_create_window(ctx); | |
22207 popup->parent = win; | |
22208 win->popup.win = popup; | |
22209 win->popup.active = 0; | |
22210 win->popup.type = NK_PANEL_POPUP; | |
22211 } | |
22212 | |
22213 /* make sure we have correct popup */ | |
22214 if (win->popup.name != title_hash) { | |
22215 if (!win->popup.active) { | |
22216 nk_zero(popup, sizeof(*popup)); | |
22217 win->popup.name = title_hash; | |
22218 win->popup.active = 1; | |
22219 win->popup.type = NK_PANEL_POPUP; | |
22220 } else return 0; | |
22221 } | |
22222 | |
22223 /* popup position is local to window */ | |
22224 ctx->current = popup; | |
22225 rect.x += win->layout->clip.x; | |
22226 rect.y += win->layout->clip.y; | |
22227 | |
22228 /* setup popup data */ | |
22229 popup->parent = win; | |
22230 popup->bounds = rect; | |
22231 popup->seq = ctx->seq; | |
22232 popup->layout = (struct nk_panel*)nk_create_panel(ctx); | |
22233 popup->flags = flags; | |
22234 popup->flags |= NK_WINDOW_BORDER; | |
22235 if (type == NK_POPUP_DYNAMIC) | |
22236 popup->flags |= NK_WINDOW_DYNAMIC; | |
22237 | |
22238 popup->buffer = win->buffer; | |
22239 nk_start_popup(ctx, win); | |
22240 allocated = ctx->memory.allocated; | |
22241 nk_push_scissor(&popup->buffer, nk_null_rect); | |
22242 | |
22243 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { | |
22244 /* popup is running therefore invalidate parent panels */ | |
22245 struct nk_panel *root; | |
22246 root = win->layout; | |
22247 while (root) { | |
22248 root->flags |= NK_WINDOW_ROM; | |
22249 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; | |
22250 root = root->parent; | |
22251 } | |
22252 win->popup.active = 1; | |
22253 popup->layout->offset_x = &popup->scrollbar.x; | |
22254 popup->layout->offset_y = &popup->scrollbar.y; | |
22255 popup->layout->parent = win->layout; | |
22256 return 1; | |
22257 } else { | |
22258 /* popup was closed/is invalid so cleanup */ | |
22259 struct nk_panel *root; | |
22260 root = win->layout; | |
22261 while (root) { | |
22262 root->flags |= NK_WINDOW_REMOVE_ROM; | |
22263 root = root->parent; | |
22264 } | |
22265 win->popup.buf.active = 0; | |
22266 win->popup.active = 0; | |
22267 ctx->memory.allocated = allocated; | |
22268 ctx->current = win; | |
22269 nk_free_panel(ctx, popup->layout); | |
22270 popup->layout = 0; | |
22271 return 0; | |
22272 } | |
22273 } | |
22274 | |
22275 NK_INTERN int | |
22276 nk_nonblock_begin(struct nk_context *ctx, | |
22277 nk_flags flags, struct nk_rect body, struct nk_rect header, | |
22278 enum nk_panel_type panel_type) | |
22279 { | |
22280 struct nk_window *popup; | |
22281 struct nk_window *win; | |
22282 struct nk_panel *panel; | |
22283 int is_active = nk_true; | |
22284 | |
22285 NK_ASSERT(ctx); | |
22286 NK_ASSERT(ctx->current); | |
22287 NK_ASSERT(ctx->current->layout); | |
22288 if (!ctx || !ctx->current || !ctx->current->layout) | |
22289 return 0; | |
22290 | |
22291 /* popups cannot have popups */ | |
22292 win = ctx->current; | |
22293 panel = win->layout; | |
22294 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); | |
22295 (void)panel; | |
22296 popup = win->popup.win; | |
22297 if (!popup) { | |
22298 /* create window for nonblocking popup */ | |
22299 popup = (struct nk_window*)nk_create_window(ctx); | |
22300 popup->parent = win; | |
22301 win->popup.win = popup; | |
22302 win->popup.type = panel_type; | |
22303 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); | |
22304 } else { | |
22305 /* close the popup if user pressed outside or in the header */ | |
22306 int pressed, in_body, in_header; | |
22307 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); | |
22308 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); | |
22309 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); | |
22310 if (pressed && (!in_body || in_header)) | |
22311 is_active = nk_false; | |
22312 } | |
22313 win->popup.header = header; | |
22314 | |
22315 if (!is_active) { | |
22316 /* remove read only mode from all parent panels */ | |
22317 struct nk_panel *root = win->layout; | |
22318 while (root) { | |
22319 root->flags |= NK_WINDOW_REMOVE_ROM; | |
22320 root = root->parent; | |
22321 } | |
22322 return is_active; | |
22323 } | |
22324 | |
22325 popup->bounds = body; | |
22326 popup->parent = win; | |
22327 popup->layout = (struct nk_panel*)nk_create_panel(ctx); | |
22328 popup->flags = flags; | |
22329 popup->flags |= NK_WINDOW_BORDER; | |
22330 popup->flags |= NK_WINDOW_DYNAMIC; | |
22331 popup->seq = ctx->seq; | |
22332 win->popup.active = 1; | |
22333 NK_ASSERT(popup->layout); | |
22334 | |
22335 nk_start_popup(ctx, win); | |
22336 popup->buffer = win->buffer; | |
22337 nk_push_scissor(&popup->buffer, nk_null_rect); | |
22338 ctx->current = popup; | |
22339 | |
22340 nk_panel_begin(ctx, 0, panel_type); | |
22341 win->buffer = popup->buffer; | |
22342 popup->layout->parent = win->layout; | |
22343 popup->layout->offset_x = &popup->scrollbar.x; | |
22344 popup->layout->offset_y = &popup->scrollbar.y; | |
22345 | |
22346 /* set read only mode to all parent panels */ | |
22347 {struct nk_panel *root; | |
22348 root = win->layout; | |
22349 while (root) { | |
22350 root->flags |= NK_WINDOW_ROM; | |
22351 root = root->parent; | |
22352 }} | |
22353 return is_active; | |
22354 } | |
22355 | |
22356 NK_API void | |
22357 nk_popup_close(struct nk_context *ctx) | |
22358 { | |
22359 struct nk_window *popup; | |
22360 NK_ASSERT(ctx); | |
22361 if (!ctx || !ctx->current) return; | |
22362 | |
22363 popup = ctx->current; | |
22364 NK_ASSERT(popup->parent); | |
22365 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); | |
22366 popup->flags |= NK_WINDOW_HIDDEN; | |
22367 } | |
22368 | |
22369 NK_API void | |
22370 nk_popup_end(struct nk_context *ctx) | |
22371 { | |
22372 struct nk_window *win; | |
22373 struct nk_window *popup; | |
22374 | |
22375 NK_ASSERT(ctx); | |
22376 NK_ASSERT(ctx->current); | |
22377 NK_ASSERT(ctx->current->layout); | |
22378 if (!ctx || !ctx->current || !ctx->current->layout) | |
22379 return; | |
22380 | |
22381 popup = ctx->current; | |
22382 if (!popup->parent) return; | |
22383 win = popup->parent; | |
22384 if (popup->flags & NK_WINDOW_HIDDEN) { | |
22385 struct nk_panel *root; | |
22386 root = win->layout; | |
22387 while (root) { | |
22388 root->flags |= NK_WINDOW_REMOVE_ROM; | |
22389 root = root->parent; | |
22390 } | |
22391 win->popup.active = 0; | |
22392 } | |
22393 nk_push_scissor(&popup->buffer, nk_null_rect); | |
22394 nk_end(ctx); | |
22395 | |
22396 win->buffer = popup->buffer; | |
22397 nk_finish_popup(ctx, win); | |
22398 ctx->current = win; | |
22399 nk_push_scissor(&win->buffer, win->layout->clip); | |
22400 } | |
22401 /* ------------------------------------------------------------- | |
22402 * | |
22403 * TOOLTIP | |
22404 * | |
22405 * -------------------------------------------------------------- */ | |
22406 NK_API int | |
22407 nk_tooltip_begin(struct nk_context *ctx, float width) | |
22408 { | |
22409 struct nk_window *win; | |
22410 const struct nk_input *in; | |
22411 struct nk_rect bounds; | |
22412 int ret; | |
22413 | |
22414 NK_ASSERT(ctx); | |
22415 NK_ASSERT(ctx->current); | |
22416 NK_ASSERT(ctx->current->layout); | |
22417 if (!ctx || !ctx->current || !ctx->current->layout) | |
22418 return 0; | |
22419 | |
22420 /* make sure that no nonblocking popup is currently active */ | |
22421 win = ctx->current; | |
22422 in = &ctx->input; | |
22423 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) | |
22424 return 0; | |
22425 | |
22426 bounds.w = width; | |
22427 bounds.h = nk_null_rect.h; | |
22428 bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x; | |
22429 bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y; | |
22430 | |
22431 ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, | |
22432 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); | |
22433 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; | |
22434 win->popup.type = NK_PANEL_TOOLTIP; | |
22435 ctx->current->layout->type = NK_PANEL_TOOLTIP; | |
22436 return ret; | |
22437 } | |
22438 | |
22439 NK_API void | |
22440 nk_tooltip_end(struct nk_context *ctx) | |
22441 { | |
22442 NK_ASSERT(ctx); | |
22443 NK_ASSERT(ctx->current); | |
22444 if (!ctx || !ctx->current) return; | |
22445 ctx->current->seq--; | |
22446 nk_popup_close(ctx); | |
22447 nk_popup_end(ctx); | |
22448 } | |
22449 | |
22450 NK_API void | |
22451 nk_tooltip(struct nk_context *ctx, const char *text) | |
22452 { | |
22453 const struct nk_style *style; | |
22454 struct nk_vec2 padding; | |
22455 | |
22456 int text_len; | |
22457 float text_width; | |
22458 float text_height; | |
22459 | |
22460 NK_ASSERT(ctx); | |
22461 NK_ASSERT(ctx->current); | |
22462 NK_ASSERT(ctx->current->layout); | |
22463 NK_ASSERT(text); | |
22464 if (!ctx || !ctx->current || !ctx->current->layout || !text) | |
22465 return; | |
22466 | |
22467 /* fetch configuration data */ | |
22468 style = &ctx->style; | |
22469 padding = style->window.padding; | |
22470 | |
22471 /* calculate size of the text and tooltip */ | |
22472 text_len = nk_strlen(text); | |
22473 text_width = style->font->width(style->font->userdata, | |
22474 style->font->height, text, text_len); | |
22475 text_width += (4 * padding.x); | |
22476 text_height = (style->font->height + 2 * padding.y); | |
22477 | |
22478 /* execute tooltip and fill with text */ | |
22479 if (nk_tooltip_begin(ctx, (float)text_width)) { | |
22480 nk_layout_row_dynamic(ctx, (float)text_height, 1); | |
22481 nk_text(ctx, text, text_len, NK_TEXT_LEFT); | |
22482 nk_tooltip_end(ctx); | |
22483 } | |
22484 } | |
22485 /* ------------------------------------------------------------- | |
22486 * | |
22487 * CONTEXTUAL | |
22488 * | |
22489 * -------------------------------------------------------------- */ | |
22490 NK_API int | |
22491 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, | |
22492 struct nk_rect trigger_bounds) | |
22493 { | |
22494 struct nk_window *win; | |
22495 struct nk_window *popup; | |
22496 struct nk_rect body; | |
22497 | |
22498 NK_STORAGE const struct nk_rect null_rect = {0,0,0,0}; | |
22499 int is_clicked = 0; | |
22500 int is_active = 0; | |
22501 int is_open = 0; | |
22502 int ret = 0; | |
22503 | |
22504 NK_ASSERT(ctx); | |
22505 NK_ASSERT(ctx->current); | |
22506 NK_ASSERT(ctx->current->layout); | |
22507 if (!ctx || !ctx->current || !ctx->current->layout) | |
22508 return 0; | |
22509 | |
22510 win = ctx->current; | |
22511 ++win->popup.con_count; | |
22512 | |
22513 /* check if currently active contextual is active */ | |
22514 popup = win->popup.win; | |
22515 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); | |
22516 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); | |
22517 if (win->popup.active_con && win->popup.con_count != win->popup.active_con) | |
22518 return 0; | |
22519 if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked)) | |
22520 return 0; | |
22521 | |
22522 /* calculate contextual position on click */ | |
22523 win->popup.active_con = win->popup.con_count; | |
22524 if (is_clicked) { | |
22525 body.x = ctx->input.mouse.pos.x; | |
22526 body.y = ctx->input.mouse.pos.y; | |
22527 } else { | |
22528 body.x = popup->bounds.x; | |
22529 body.y = popup->bounds.y; | |
22530 } | |
22531 body.w = size.x; | |
22532 body.h = size.y; | |
22533 | |
22534 /* start nonblocking contextual popup */ | |
22535 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, | |
22536 null_rect, NK_PANEL_CONTEXTUAL); | |
22537 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; | |
22538 else { | |
22539 win->popup.active_con = 0; | |
22540 if (win->popup.win) | |
22541 win->popup.win->flags = 0; | |
22542 } | |
22543 return ret; | |
22544 } | |
22545 | |
22546 NK_API int | |
22547 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, | |
22548 nk_flags alignment) | |
22549 { | |
22550 struct nk_window *win; | |
22551 const struct nk_input *in; | |
22552 const struct nk_style *style; | |
22553 | |
22554 struct nk_rect bounds; | |
22555 enum nk_widget_layout_states state; | |
22556 | |
22557 NK_ASSERT(ctx); | |
22558 NK_ASSERT(ctx->current); | |
22559 NK_ASSERT(ctx->current->layout); | |
22560 if (!ctx || !ctx->current || !ctx->current->layout) | |
22561 return 0; | |
22562 | |
22563 win = ctx->current; | |
22564 style = &ctx->style; | |
22565 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); | |
22566 if (!state) return nk_false; | |
22567 | |
22568 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
22569 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, | |
22570 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { | |
22571 nk_contextual_close(ctx); | |
22572 return nk_true; | |
22573 } | |
22574 return nk_false; | |
22575 } | |
22576 | |
22577 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) | |
22578 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);} | |
22579 | |
22580 NK_API int | |
22581 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, | |
22582 const char *text, int len, nk_flags align) | |
22583 { | |
22584 struct nk_window *win; | |
22585 const struct nk_input *in; | |
22586 const struct nk_style *style; | |
22587 | |
22588 struct nk_rect bounds; | |
22589 enum nk_widget_layout_states state; | |
22590 | |
22591 NK_ASSERT(ctx); | |
22592 NK_ASSERT(ctx->current); | |
22593 NK_ASSERT(ctx->current->layout); | |
22594 if (!ctx || !ctx->current || !ctx->current->layout) | |
22595 return 0; | |
22596 | |
22597 win = ctx->current; | |
22598 style = &ctx->style; | |
22599 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); | |
22600 if (!state) return nk_false; | |
22601 | |
22602 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
22603 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, | |
22604 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ | |
22605 nk_contextual_close(ctx); | |
22606 return nk_true; | |
22607 } | |
22608 return nk_false; | |
22609 } | |
22610 | |
22611 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, | |
22612 const char *label, nk_flags align) | |
22613 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);} | |
22614 | |
22615 NK_API int | |
22616 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, | |
22617 const char *text, int len, nk_flags align) | |
22618 { | |
22619 struct nk_window *win; | |
22620 const struct nk_input *in; | |
22621 const struct nk_style *style; | |
22622 | |
22623 struct nk_rect bounds; | |
22624 enum nk_widget_layout_states state; | |
22625 | |
22626 NK_ASSERT(ctx); | |
22627 NK_ASSERT(ctx->current); | |
22628 NK_ASSERT(ctx->current->layout); | |
22629 if (!ctx || !ctx->current || !ctx->current->layout) | |
22630 return 0; | |
22631 | |
22632 win = ctx->current; | |
22633 style = &ctx->style; | |
22634 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); | |
22635 if (!state) return nk_false; | |
22636 | |
22637 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
22638 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, | |
22639 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { | |
22640 nk_contextual_close(ctx); | |
22641 return nk_true; | |
22642 } | |
22643 return nk_false; | |
22644 } | |
22645 | |
22646 NK_API int nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, | |
22647 const char *text, nk_flags align) | |
22648 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);} | |
22649 | |
22650 NK_API void | |
22651 nk_contextual_close(struct nk_context *ctx) | |
22652 { | |
22653 NK_ASSERT(ctx); | |
22654 NK_ASSERT(ctx->current); | |
22655 NK_ASSERT(ctx->current->layout); | |
22656 if (!ctx || !ctx->current || !ctx->current->layout) return; | |
22657 nk_popup_close(ctx); | |
22658 } | |
22659 | |
22660 NK_API void | |
22661 nk_contextual_end(struct nk_context *ctx) | |
22662 { | |
22663 struct nk_window *popup; | |
22664 struct nk_panel *panel; | |
22665 NK_ASSERT(ctx); | |
22666 NK_ASSERT(ctx->current); | |
22667 if (!ctx || !ctx->current) return; | |
22668 | |
22669 popup = ctx->current; | |
22670 panel = popup->layout; | |
22671 NK_ASSERT(popup->parent); | |
22672 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); | |
22673 if (panel->flags & NK_WINDOW_DYNAMIC) { | |
22674 /* Close behavior | |
22675 This is a bit of a hack solution since we do not know before we end our popup | |
22676 how big it will be. We therefore do not directly know when a | |
22677 click outside the non-blocking popup must close it at that direct frame. | |
22678 Instead it will be closed in the next frame.*/ | |
22679 struct nk_rect body = {0,0,0,0}; | |
22680 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { | |
22681 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); | |
22682 body = panel->bounds; | |
22683 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); | |
22684 body.h = (panel->bounds.y + panel->bounds.h) - body.y; | |
22685 } | |
22686 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); | |
22687 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); | |
22688 if (pressed && in_body) | |
22689 popup->flags |= NK_WINDOW_HIDDEN; | |
22690 } | |
22691 } | |
22692 if (popup->flags & NK_WINDOW_HIDDEN) | |
22693 popup->seq = 0; | |
22694 nk_popup_end(ctx); | |
22695 return; | |
22696 } | |
22697 /* ------------------------------------------------------------- | |
22698 * | |
22699 * COMBO | |
22700 * | |
22701 * --------------------------------------------------------------*/ | |
22702 NK_INTERN int | |
22703 nk_combo_begin(struct nk_context *ctx, struct nk_window *win, | |
22704 struct nk_vec2 size, int is_clicked, struct nk_rect header) | |
22705 { | |
22706 struct nk_window *popup; | |
22707 int is_open = 0; | |
22708 int is_active = 0; | |
22709 struct nk_rect body; | |
22710 nk_hash hash; | |
22711 | |
22712 NK_ASSERT(ctx); | |
22713 NK_ASSERT(ctx->current); | |
22714 NK_ASSERT(ctx->current->layout); | |
22715 if (!ctx || !ctx->current || !ctx->current->layout) | |
22716 return 0; | |
22717 | |
22718 popup = win->popup.win; | |
22719 body.x = header.x; | |
22720 body.w = size.x; | |
22721 body.y = header.y + header.h-ctx->style.window.combo_border; | |
22722 body.h = size.y; | |
22723 | |
22724 hash = win->popup.combo_count++; | |
22725 is_open = (popup) ? nk_true:nk_false; | |
22726 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); | |
22727 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || | |
22728 (!is_open && !is_active && !is_clicked)) return 0; | |
22729 if (!nk_nonblock_begin(ctx, 0, body, | |
22730 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; | |
22731 | |
22732 win->popup.type = NK_PANEL_COMBO; | |
22733 win->popup.name = hash; | |
22734 return 1; | |
22735 } | |
22736 | |
22737 NK_API int | |
22738 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, | |
22739 struct nk_vec2 size) | |
22740 { | |
22741 const struct nk_input *in; | |
22742 struct nk_window *win; | |
22743 struct nk_style *style; | |
22744 | |
22745 enum nk_widget_layout_states s; | |
22746 int is_clicked = nk_false; | |
22747 struct nk_rect header; | |
22748 const struct nk_style_item *background; | |
22749 struct nk_text text; | |
22750 | |
22751 NK_ASSERT(ctx); | |
22752 NK_ASSERT(selected); | |
22753 NK_ASSERT(ctx->current); | |
22754 NK_ASSERT(ctx->current->layout); | |
22755 if (!ctx || !ctx->current || !ctx->current->layout || !selected) | |
22756 return 0; | |
22757 | |
22758 win = ctx->current; | |
22759 style = &ctx->style; | |
22760 s = nk_widget(&header, ctx); | |
22761 if (s == NK_WIDGET_INVALID) | |
22762 return 0; | |
22763 | |
22764 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
22765 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
22766 is_clicked = nk_true; | |
22767 | |
22768 /* draw combo box header background and border */ | |
22769 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { | |
22770 background = &style->combo.active; | |
22771 text.text = style->combo.label_active; | |
22772 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { | |
22773 background = &style->combo.hover; | |
22774 text.text = style->combo.label_hover; | |
22775 } else { | |
22776 background = &style->combo.normal; | |
22777 text.text = style->combo.label_normal; | |
22778 } | |
22779 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
22780 text.background = nk_rgba(0,0,0,0); | |
22781 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
22782 } else { | |
22783 text.background = background->data.color; | |
22784 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
22785 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
22786 } | |
22787 { | |
22788 /* print currently selected text item */ | |
22789 struct nk_rect label; | |
22790 struct nk_rect button; | |
22791 struct nk_rect content; | |
22792 | |
22793 enum nk_symbol_type sym; | |
22794 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
22795 sym = style->combo.sym_hover; | |
22796 else if (is_clicked) | |
22797 sym = style->combo.sym_active; | |
22798 else sym = style->combo.sym_normal; | |
22799 | |
22800 /* calculate button */ | |
22801 button.w = header.h - 2 * style->combo.button_padding.y; | |
22802 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; | |
22803 button.y = header.y + style->combo.button_padding.y; | |
22804 button.h = button.w; | |
22805 | |
22806 content.x = button.x + style->combo.button.padding.x; | |
22807 content.y = button.y + style->combo.button.padding.y; | |
22808 content.w = button.w - 2 * style->combo.button.padding.x; | |
22809 content.h = button.h - 2 * style->combo.button.padding.y; | |
22810 | |
22811 /* draw selected label */ | |
22812 text.padding = nk_vec2(0,0); | |
22813 label.x = header.x + style->combo.content_padding.x; | |
22814 label.y = header.y + style->combo.content_padding.y; | |
22815 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; | |
22816 label.h = header.h - 2 * style->combo.content_padding.y; | |
22817 nk_widget_text(&win->buffer, label, selected, len, &text, | |
22818 NK_TEXT_LEFT, ctx->style.font); | |
22819 | |
22820 /* draw open/close button */ | |
22821 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, | |
22822 &ctx->style.combo.button, sym, style->font); | |
22823 } | |
22824 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
22825 } | |
22826 | |
22827 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) | |
22828 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);} | |
22829 | |
22830 NK_API int | |
22831 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) | |
22832 { | |
22833 struct nk_window *win; | |
22834 struct nk_style *style; | |
22835 const struct nk_input *in; | |
22836 | |
22837 struct nk_rect header; | |
22838 int is_clicked = nk_false; | |
22839 enum nk_widget_layout_states s; | |
22840 const struct nk_style_item *background; | |
22841 | |
22842 NK_ASSERT(ctx); | |
22843 NK_ASSERT(ctx->current); | |
22844 NK_ASSERT(ctx->current->layout); | |
22845 if (!ctx || !ctx->current || !ctx->current->layout) | |
22846 return 0; | |
22847 | |
22848 win = ctx->current; | |
22849 style = &ctx->style; | |
22850 s = nk_widget(&header, ctx); | |
22851 if (s == NK_WIDGET_INVALID) | |
22852 return 0; | |
22853 | |
22854 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
22855 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
22856 is_clicked = nk_true; | |
22857 | |
22858 /* draw combo box header background and border */ | |
22859 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) | |
22860 background = &style->combo.active; | |
22861 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
22862 background = &style->combo.hover; | |
22863 else background = &style->combo.normal; | |
22864 | |
22865 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
22866 nk_draw_image(&win->buffer, header, &background->data.image,nk_white); | |
22867 } else { | |
22868 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
22869 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
22870 } | |
22871 { | |
22872 struct nk_rect content; | |
22873 struct nk_rect button; | |
22874 struct nk_rect bounds; | |
22875 | |
22876 enum nk_symbol_type sym; | |
22877 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
22878 sym = style->combo.sym_hover; | |
22879 else if (is_clicked) | |
22880 sym = style->combo.sym_active; | |
22881 else sym = style->combo.sym_normal; | |
22882 | |
22883 /* calculate button */ | |
22884 button.w = header.h - 2 * style->combo.button_padding.y; | |
22885 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; | |
22886 button.y = header.y + style->combo.button_padding.y; | |
22887 button.h = button.w; | |
22888 | |
22889 content.x = button.x + style->combo.button.padding.x; | |
22890 content.y = button.y + style->combo.button.padding.y; | |
22891 content.w = button.w - 2 * style->combo.button.padding.x; | |
22892 content.h = button.h - 2 * style->combo.button.padding.y; | |
22893 | |
22894 /* draw color */ | |
22895 bounds.h = header.h - 4 * style->combo.content_padding.y; | |
22896 bounds.y = header.y + 2 * style->combo.content_padding.y; | |
22897 bounds.x = header.x + 2 * style->combo.content_padding.x; | |
22898 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; | |
22899 nk_fill_rect(&win->buffer, bounds, 0, color); | |
22900 | |
22901 /* draw open/close button */ | |
22902 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, | |
22903 &ctx->style.combo.button, sym, style->font); | |
22904 } | |
22905 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
22906 } | |
22907 | |
22908 NK_API int | |
22909 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) | |
22910 { | |
22911 struct nk_window *win; | |
22912 struct nk_style *style; | |
22913 const struct nk_input *in; | |
22914 | |
22915 struct nk_rect header; | |
22916 int is_clicked = nk_false; | |
22917 enum nk_widget_layout_states s; | |
22918 const struct nk_style_item *background; | |
22919 struct nk_color sym_background; | |
22920 struct nk_color symbol_color; | |
22921 | |
22922 NK_ASSERT(ctx); | |
22923 NK_ASSERT(ctx->current); | |
22924 NK_ASSERT(ctx->current->layout); | |
22925 if (!ctx || !ctx->current || !ctx->current->layout) | |
22926 return 0; | |
22927 | |
22928 win = ctx->current; | |
22929 style = &ctx->style; | |
22930 s = nk_widget(&header, ctx); | |
22931 if (s == NK_WIDGET_INVALID) | |
22932 return 0; | |
22933 | |
22934 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
22935 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
22936 is_clicked = nk_true; | |
22937 | |
22938 /* draw combo box header background and border */ | |
22939 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { | |
22940 background = &style->combo.active; | |
22941 symbol_color = style->combo.symbol_active; | |
22942 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { | |
22943 background = &style->combo.hover; | |
22944 symbol_color = style->combo.symbol_hover; | |
22945 } else { | |
22946 background = &style->combo.normal; | |
22947 symbol_color = style->combo.symbol_hover; | |
22948 } | |
22949 | |
22950 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
22951 sym_background = nk_rgba(0,0,0,0); | |
22952 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
22953 } else { | |
22954 sym_background = background->data.color; | |
22955 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
22956 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
22957 } | |
22958 { | |
22959 struct nk_rect bounds = {0,0,0,0}; | |
22960 struct nk_rect content; | |
22961 struct nk_rect button; | |
22962 | |
22963 enum nk_symbol_type sym; | |
22964 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
22965 sym = style->combo.sym_hover; | |
22966 else if (is_clicked) | |
22967 sym = style->combo.sym_active; | |
22968 else sym = style->combo.sym_normal; | |
22969 | |
22970 /* calculate button */ | |
22971 button.w = header.h - 2 * style->combo.button_padding.y; | |
22972 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; | |
22973 button.y = header.y + style->combo.button_padding.y; | |
22974 button.h = button.w; | |
22975 | |
22976 content.x = button.x + style->combo.button.padding.x; | |
22977 content.y = button.y + style->combo.button.padding.y; | |
22978 content.w = button.w - 2 * style->combo.button.padding.x; | |
22979 content.h = button.h - 2 * style->combo.button.padding.y; | |
22980 | |
22981 /* draw symbol */ | |
22982 bounds.h = header.h - 2 * style->combo.content_padding.y; | |
22983 bounds.y = header.y + style->combo.content_padding.y; | |
22984 bounds.x = header.x + style->combo.content_padding.x; | |
22985 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; | |
22986 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, | |
22987 1.0f, style->font); | |
22988 | |
22989 /* draw open/close button */ | |
22990 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, | |
22991 &ctx->style.combo.button, sym, style->font); | |
22992 } | |
22993 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
22994 } | |
22995 | |
22996 NK_API int | |
22997 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, | |
22998 enum nk_symbol_type symbol, struct nk_vec2 size) | |
22999 { | |
23000 struct nk_window *win; | |
23001 struct nk_style *style; | |
23002 struct nk_input *in; | |
23003 | |
23004 struct nk_rect header; | |
23005 int is_clicked = nk_false; | |
23006 enum nk_widget_layout_states s; | |
23007 const struct nk_style_item *background; | |
23008 struct nk_color symbol_color; | |
23009 struct nk_text text; | |
23010 | |
23011 NK_ASSERT(ctx); | |
23012 NK_ASSERT(ctx->current); | |
23013 NK_ASSERT(ctx->current->layout); | |
23014 if (!ctx || !ctx->current || !ctx->current->layout) | |
23015 return 0; | |
23016 | |
23017 win = ctx->current; | |
23018 style = &ctx->style; | |
23019 s = nk_widget(&header, ctx); | |
23020 if (!s) return 0; | |
23021 | |
23022 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
23023 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
23024 is_clicked = nk_true; | |
23025 | |
23026 /* draw combo box header background and border */ | |
23027 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { | |
23028 background = &style->combo.active; | |
23029 symbol_color = style->combo.symbol_active; | |
23030 text.text = style->combo.label_active; | |
23031 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { | |
23032 background = &style->combo.hover; | |
23033 symbol_color = style->combo.symbol_hover; | |
23034 text.text = style->combo.label_hover; | |
23035 } else { | |
23036 background = &style->combo.normal; | |
23037 symbol_color = style->combo.symbol_normal; | |
23038 text.text = style->combo.label_normal; | |
23039 } | |
23040 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
23041 text.background = nk_rgba(0,0,0,0); | |
23042 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
23043 } else { | |
23044 text.background = background->data.color; | |
23045 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
23046 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
23047 } | |
23048 { | |
23049 struct nk_rect content; | |
23050 struct nk_rect button; | |
23051 struct nk_rect label; | |
23052 struct nk_rect image; | |
23053 | |
23054 enum nk_symbol_type sym; | |
23055 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
23056 sym = style->combo.sym_hover; | |
23057 else if (is_clicked) | |
23058 sym = style->combo.sym_active; | |
23059 else sym = style->combo.sym_normal; | |
23060 | |
23061 /* calculate button */ | |
23062 button.w = header.h - 2 * style->combo.button_padding.y; | |
23063 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; | |
23064 button.y = header.y + style->combo.button_padding.y; | |
23065 button.h = button.w; | |
23066 | |
23067 content.x = button.x + style->combo.button.padding.x; | |
23068 content.y = button.y + style->combo.button.padding.y; | |
23069 content.w = button.w - 2 * style->combo.button.padding.x; | |
23070 content.h = button.h - 2 * style->combo.button.padding.y; | |
23071 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, | |
23072 &ctx->style.combo.button, sym, style->font); | |
23073 | |
23074 /* draw symbol */ | |
23075 image.x = header.x + style->combo.content_padding.x; | |
23076 image.y = header.y + style->combo.content_padding.y; | |
23077 image.h = header.h - 2 * style->combo.content_padding.y; | |
23078 image.w = image.h; | |
23079 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, | |
23080 1.0f, style->font); | |
23081 | |
23082 /* draw label */ | |
23083 text.padding = nk_vec2(0,0); | |
23084 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; | |
23085 label.y = header.y + style->combo.content_padding.y; | |
23086 label.w = (button.x - style->combo.content_padding.x) - label.x; | |
23087 label.h = header.h - 2 * style->combo.content_padding.y; | |
23088 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); | |
23089 } | |
23090 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
23091 } | |
23092 | |
23093 NK_API int | |
23094 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) | |
23095 { | |
23096 struct nk_window *win; | |
23097 struct nk_style *style; | |
23098 const struct nk_input *in; | |
23099 | |
23100 struct nk_rect header; | |
23101 int is_clicked = nk_false; | |
23102 enum nk_widget_layout_states s; | |
23103 const struct nk_style_item *background; | |
23104 | |
23105 NK_ASSERT(ctx); | |
23106 NK_ASSERT(ctx->current); | |
23107 NK_ASSERT(ctx->current->layout); | |
23108 if (!ctx || !ctx->current || !ctx->current->layout) | |
23109 return 0; | |
23110 | |
23111 win = ctx->current; | |
23112 style = &ctx->style; | |
23113 s = nk_widget(&header, ctx); | |
23114 if (s == NK_WIDGET_INVALID) | |
23115 return 0; | |
23116 | |
23117 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
23118 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
23119 is_clicked = nk_true; | |
23120 | |
23121 /* draw combo box header background and border */ | |
23122 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) | |
23123 background = &style->combo.active; | |
23124 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
23125 background = &style->combo.hover; | |
23126 else background = &style->combo.normal; | |
23127 | |
23128 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
23129 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
23130 } else { | |
23131 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
23132 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
23133 } | |
23134 { | |
23135 struct nk_rect bounds = {0,0,0,0}; | |
23136 struct nk_rect content; | |
23137 struct nk_rect button; | |
23138 | |
23139 enum nk_symbol_type sym; | |
23140 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
23141 sym = style->combo.sym_hover; | |
23142 else if (is_clicked) | |
23143 sym = style->combo.sym_active; | |
23144 else sym = style->combo.sym_normal; | |
23145 | |
23146 /* calculate button */ | |
23147 button.w = header.h - 2 * style->combo.button_padding.y; | |
23148 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; | |
23149 button.y = header.y + style->combo.button_padding.y; | |
23150 button.h = button.w; | |
23151 | |
23152 content.x = button.x + style->combo.button.padding.x; | |
23153 content.y = button.y + style->combo.button.padding.y; | |
23154 content.w = button.w - 2 * style->combo.button.padding.x; | |
23155 content.h = button.h - 2 * style->combo.button.padding.y; | |
23156 | |
23157 /* draw image */ | |
23158 bounds.h = header.h - 2 * style->combo.content_padding.y; | |
23159 bounds.y = header.y + style->combo.content_padding.y; | |
23160 bounds.x = header.x + style->combo.content_padding.x; | |
23161 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; | |
23162 nk_draw_image(&win->buffer, bounds, &img, nk_white); | |
23163 | |
23164 /* draw open/close button */ | |
23165 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, | |
23166 &ctx->style.combo.button, sym, style->font); | |
23167 } | |
23168 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
23169 } | |
23170 | |
23171 NK_API int | |
23172 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, | |
23173 struct nk_image img, struct nk_vec2 size) | |
23174 { | |
23175 struct nk_window *win; | |
23176 struct nk_style *style; | |
23177 struct nk_input *in; | |
23178 | |
23179 struct nk_rect header; | |
23180 int is_clicked = nk_false; | |
23181 enum nk_widget_layout_states s; | |
23182 const struct nk_style_item *background; | |
23183 struct nk_text text; | |
23184 | |
23185 NK_ASSERT(ctx); | |
23186 NK_ASSERT(ctx->current); | |
23187 NK_ASSERT(ctx->current->layout); | |
23188 if (!ctx || !ctx->current || !ctx->current->layout) | |
23189 return 0; | |
23190 | |
23191 win = ctx->current; | |
23192 style = &ctx->style; | |
23193 s = nk_widget(&header, ctx); | |
23194 if (!s) return 0; | |
23195 | |
23196 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; | |
23197 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) | |
23198 is_clicked = nk_true; | |
23199 | |
23200 /* draw combo box header background and border */ | |
23201 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { | |
23202 background = &style->combo.active; | |
23203 text.text = style->combo.label_active; | |
23204 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { | |
23205 background = &style->combo.hover; | |
23206 text.text = style->combo.label_hover; | |
23207 } else { | |
23208 background = &style->combo.normal; | |
23209 text.text = style->combo.label_normal; | |
23210 } | |
23211 if (background->type == NK_STYLE_ITEM_IMAGE) { | |
23212 text.background = nk_rgba(0,0,0,0); | |
23213 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); | |
23214 } else { | |
23215 text.background = background->data.color; | |
23216 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); | |
23217 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); | |
23218 } | |
23219 { | |
23220 struct nk_rect content; | |
23221 struct nk_rect button; | |
23222 struct nk_rect label; | |
23223 struct nk_rect image; | |
23224 | |
23225 enum nk_symbol_type sym; | |
23226 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) | |
23227 sym = style->combo.sym_hover; | |
23228 else if (is_clicked) | |
23229 sym = style->combo.sym_active; | |
23230 else sym = style->combo.sym_normal; | |
23231 | |
23232 /* calculate button */ | |
23233 button.w = header.h - 2 * style->combo.button_padding.y; | |
23234 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; | |
23235 button.y = header.y + style->combo.button_padding.y; | |
23236 button.h = button.w; | |
23237 | |
23238 content.x = button.x + style->combo.button.padding.x; | |
23239 content.y = button.y + style->combo.button.padding.y; | |
23240 content.w = button.w - 2 * style->combo.button.padding.x; | |
23241 content.h = button.h - 2 * style->combo.button.padding.y; | |
23242 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, | |
23243 &ctx->style.combo.button, sym, style->font); | |
23244 | |
23245 /* draw image */ | |
23246 image.x = header.x + style->combo.content_padding.x; | |
23247 image.y = header.y + style->combo.content_padding.y; | |
23248 image.h = header.h - 2 * style->combo.content_padding.y; | |
23249 image.w = image.h; | |
23250 nk_draw_image(&win->buffer, image, &img, nk_white); | |
23251 | |
23252 /* draw label */ | |
23253 text.padding = nk_vec2(0,0); | |
23254 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; | |
23255 label.y = header.y + style->combo.content_padding.y; | |
23256 label.w = (button.x - style->combo.content_padding.x) - label.x; | |
23257 label.h = header.h - 2 * style->combo.content_padding.y; | |
23258 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); | |
23259 } | |
23260 return nk_combo_begin(ctx, win, size, is_clicked, header); | |
23261 } | |
23262 | |
23263 NK_API int nk_combo_begin_symbol_label(struct nk_context *ctx, | |
23264 const char *selected, enum nk_symbol_type type, struct nk_vec2 size) | |
23265 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);} | |
23266 | |
23267 NK_API int nk_combo_begin_image_label(struct nk_context *ctx, | |
23268 const char *selected, struct nk_image img, struct nk_vec2 size) | |
23269 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);} | |
23270 | |
23271 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) | |
23272 {return nk_contextual_item_text(ctx, text, len, align);} | |
23273 | |
23274 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) | |
23275 {return nk_contextual_item_label(ctx, label, align);} | |
23276 | |
23277 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, | |
23278 int len, nk_flags alignment) | |
23279 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);} | |
23280 | |
23281 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, | |
23282 const char *text, nk_flags alignment) | |
23283 {return nk_contextual_item_image_label(ctx, img, text, alignment);} | |
23284 | |
23285 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, | |
23286 const char *text, int len, nk_flags alignment) | |
23287 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);} | |
23288 | |
23289 NK_API int nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, | |
23290 const char *label, nk_flags alignment) | |
23291 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);} | |
23292 | |
23293 NK_API void nk_combo_end(struct nk_context *ctx) | |
23294 {nk_contextual_end(ctx);} | |
23295 | |
23296 NK_API void nk_combo_close(struct nk_context *ctx) | |
23297 {nk_contextual_close(ctx);} | |
23298 | |
23299 NK_API int | |
23300 nk_combo(struct nk_context *ctx, const char **items, int count, | |
23301 int selected, int item_height, struct nk_vec2 size) | |
23302 { | |
23303 int i = 0; | |
23304 int max_height; | |
23305 struct nk_vec2 item_spacing; | |
23306 struct nk_vec2 window_padding; | |
23307 | |
23308 NK_ASSERT(ctx); | |
23309 NK_ASSERT(items); | |
23310 NK_ASSERT(ctx->current); | |
23311 if (!ctx || !items ||!count) | |
23312 return selected; | |
23313 | |
23314 item_spacing = ctx->style.window.spacing; | |
23315 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); | |
23316 max_height = count * item_height + count * (int)item_spacing.y; | |
23317 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; | |
23318 size.y = NK_MIN(size.y, (float)max_height); | |
23319 if (nk_combo_begin_label(ctx, items[selected], size)) { | |
23320 nk_layout_row_dynamic(ctx, (float)item_height, 1); | |
23321 for (i = 0; i < count; ++i) { | |
23322 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) | |
23323 selected = i; | |
23324 } | |
23325 nk_combo_end(ctx); | |
23326 } | |
23327 return selected; | |
23328 } | |
23329 | |
23330 NK_API int | |
23331 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, | |
23332 int separator, int selected, int count, int item_height, struct nk_vec2 size) | |
23333 { | |
23334 int i; | |
23335 int max_height; | |
23336 struct nk_vec2 item_spacing; | |
23337 struct nk_vec2 window_padding; | |
23338 const char *current_item; | |
23339 const char *iter; | |
23340 int length = 0; | |
23341 | |
23342 NK_ASSERT(ctx); | |
23343 NK_ASSERT(items_separated_by_separator); | |
23344 if (!ctx || !items_separated_by_separator) | |
23345 return selected; | |
23346 | |
23347 /* calculate popup window */ | |
23348 item_spacing = ctx->style.window.spacing; | |
23349 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); | |
23350 max_height = count * item_height + count * (int)item_spacing.y; | |
23351 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; | |
23352 size.y = NK_MIN(size.y, (float)max_height); | |
23353 | |
23354 /* find selected item */ | |
23355 current_item = items_separated_by_separator; | |
23356 for (i = 0; i < count; ++i) { | |
23357 iter = current_item; | |
23358 while (*iter && *iter != separator) iter++; | |
23359 length = (int)(iter - current_item); | |
23360 if (i == selected) break; | |
23361 current_item = iter + 1; | |
23362 } | |
23363 | |
23364 if (nk_combo_begin_text(ctx, current_item, length, size)) { | |
23365 current_item = items_separated_by_separator; | |
23366 nk_layout_row_dynamic(ctx, (float)item_height, 1); | |
23367 for (i = 0; i < count; ++i) { | |
23368 iter = current_item; | |
23369 while (*iter && *iter != separator) iter++; | |
23370 length = (int)(iter - current_item); | |
23371 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) | |
23372 selected = i; | |
23373 current_item = current_item + length + 1; | |
23374 } | |
23375 nk_combo_end(ctx); | |
23376 } | |
23377 return selected; | |
23378 } | |
23379 | |
23380 NK_API int | |
23381 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, | |
23382 int selected, int count, int item_height, struct nk_vec2 size) | |
23383 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);} | |
23384 | |
23385 NK_API int | |
23386 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), | |
23387 void *userdata, int selected, int count, int item_height, struct nk_vec2 size) | |
23388 { | |
23389 int i; | |
23390 int max_height; | |
23391 struct nk_vec2 item_spacing; | |
23392 struct nk_vec2 window_padding; | |
23393 const char *item; | |
23394 | |
23395 NK_ASSERT(ctx); | |
23396 NK_ASSERT(item_getter); | |
23397 if (!ctx || !item_getter) | |
23398 return selected; | |
23399 | |
23400 /* calculate popup window */ | |
23401 item_spacing = ctx->style.window.spacing; | |
23402 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); | |
23403 max_height = count * item_height + count * (int)item_spacing.y; | |
23404 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; | |
23405 size.y = NK_MIN(size.y, (float)max_height); | |
23406 | |
23407 item_getter(userdata, selected, &item); | |
23408 if (nk_combo_begin_label(ctx, item, size)) { | |
23409 nk_layout_row_dynamic(ctx, (float)item_height, 1); | |
23410 for (i = 0; i < count; ++i) { | |
23411 item_getter(userdata, i, &item); | |
23412 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) | |
23413 selected = i; | |
23414 } | |
23415 nk_combo_end(ctx); | |
23416 } | |
23417 return selected; | |
23418 } | |
23419 | |
23420 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count, | |
23421 int *selected, int item_height, struct nk_vec2 size) | |
23422 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);} | |
23423 | |
23424 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, | |
23425 int *selected, int count, int item_height, struct nk_vec2 size) | |
23426 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);} | |
23427 | |
23428 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, | |
23429 int separator,int *selected, int count, int item_height, struct nk_vec2 size) | |
23430 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator, | |
23431 *selected, count, item_height, size);} | |
23432 | |
23433 NK_API void nk_combobox_callback(struct nk_context *ctx, | |
23434 void(*item_getter)(void* data, int id, const char **out_text), | |
23435 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) | |
23436 {*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);} | |
23437 | |
23438 /* | |
23439 * ------------------------------------------------------------- | |
23440 * | |
23441 * MENU | |
23442 * | |
23443 * -------------------------------------------------------------- | |
23444 */ | |
23445 NK_INTERN int | |
23446 nk_menu_begin(struct nk_context *ctx, struct nk_window *win, | |
23447 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) | |
23448 { | |
23449 int is_open = 0; | |
23450 int is_active = 0; | |
23451 struct nk_rect body; | |
23452 struct nk_window *popup; | |
23453 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); | |
23454 | |
23455 NK_ASSERT(ctx); | |
23456 NK_ASSERT(ctx->current); | |
23457 NK_ASSERT(ctx->current->layout); | |
23458 if (!ctx || !ctx->current || !ctx->current->layout) | |
23459 return 0; | |
23460 | |
23461 body.x = header.x; | |
23462 body.w = size.x; | |
23463 body.y = header.y + header.h; | |
23464 body.h = size.y; | |
23465 | |
23466 popup = win->popup.win; | |
23467 is_open = popup ? nk_true : nk_false; | |
23468 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); | |
23469 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || | |
23470 (!is_open && !is_active && !is_clicked)) return 0; | |
23471 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) | |
23472 return 0; | |
23473 | |
23474 win->popup.type = NK_PANEL_MENU; | |
23475 win->popup.name = hash; | |
23476 return 1; | |
23477 } | |
23478 | |
23479 NK_API int | |
23480 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, | |
23481 nk_flags align, struct nk_vec2 size) | |
23482 { | |
23483 struct nk_window *win; | |
23484 const struct nk_input *in; | |
23485 struct nk_rect header; | |
23486 int is_clicked = nk_false; | |
23487 nk_flags state; | |
23488 | |
23489 NK_ASSERT(ctx); | |
23490 NK_ASSERT(ctx->current); | |
23491 NK_ASSERT(ctx->current->layout); | |
23492 if (!ctx || !ctx->current || !ctx->current->layout) | |
23493 return 0; | |
23494 | |
23495 win = ctx->current; | |
23496 state = nk_widget(&header, ctx); | |
23497 if (!state) return 0; | |
23498 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
23499 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, | |
23500 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) | |
23501 is_clicked = nk_true; | |
23502 return nk_menu_begin(ctx, win, title, is_clicked, header, size); | |
23503 } | |
23504 | |
23505 NK_API int nk_menu_begin_label(struct nk_context *ctx, | |
23506 const char *text, nk_flags align, struct nk_vec2 size) | |
23507 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);} | |
23508 | |
23509 NK_API int | |
23510 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, | |
23511 struct nk_vec2 size) | |
23512 { | |
23513 struct nk_window *win; | |
23514 struct nk_rect header; | |
23515 const struct nk_input *in; | |
23516 int is_clicked = nk_false; | |
23517 nk_flags state; | |
23518 | |
23519 NK_ASSERT(ctx); | |
23520 NK_ASSERT(ctx->current); | |
23521 NK_ASSERT(ctx->current->layout); | |
23522 if (!ctx || !ctx->current || !ctx->current->layout) | |
23523 return 0; | |
23524 | |
23525 win = ctx->current; | |
23526 state = nk_widget(&header, ctx); | |
23527 if (!state) return 0; | |
23528 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
23529 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, | |
23530 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) | |
23531 is_clicked = nk_true; | |
23532 return nk_menu_begin(ctx, win, id, is_clicked, header, size); | |
23533 } | |
23534 | |
23535 NK_API int | |
23536 nk_menu_begin_symbol(struct nk_context *ctx, const char *id, | |
23537 enum nk_symbol_type sym, struct nk_vec2 size) | |
23538 { | |
23539 struct nk_window *win; | |
23540 const struct nk_input *in; | |
23541 struct nk_rect header; | |
23542 int is_clicked = nk_false; | |
23543 nk_flags state; | |
23544 | |
23545 NK_ASSERT(ctx); | |
23546 NK_ASSERT(ctx->current); | |
23547 NK_ASSERT(ctx->current->layout); | |
23548 if (!ctx || !ctx->current || !ctx->current->layout) | |
23549 return 0; | |
23550 | |
23551 win = ctx->current; | |
23552 state = nk_widget(&header, ctx); | |
23553 if (!state) return 0; | |
23554 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
23555 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, | |
23556 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) | |
23557 is_clicked = nk_true; | |
23558 return nk_menu_begin(ctx, win, id, is_clicked, header, size); | |
23559 } | |
23560 | |
23561 NK_API int | |
23562 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, | |
23563 nk_flags align, struct nk_image img, struct nk_vec2 size) | |
23564 { | |
23565 struct nk_window *win; | |
23566 struct nk_rect header; | |
23567 const struct nk_input *in; | |
23568 int is_clicked = nk_false; | |
23569 nk_flags state; | |
23570 | |
23571 NK_ASSERT(ctx); | |
23572 NK_ASSERT(ctx->current); | |
23573 NK_ASSERT(ctx->current->layout); | |
23574 if (!ctx || !ctx->current || !ctx->current->layout) | |
23575 return 0; | |
23576 | |
23577 win = ctx->current; | |
23578 state = nk_widget(&header, ctx); | |
23579 if (!state) return 0; | |
23580 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
23581 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, | |
23582 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, | |
23583 ctx->style.font, in)) | |
23584 is_clicked = nk_true; | |
23585 return nk_menu_begin(ctx, win, title, is_clicked, header, size); | |
23586 } | |
23587 | |
23588 NK_API int nk_menu_begin_image_label(struct nk_context *ctx, | |
23589 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) | |
23590 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);} | |
23591 | |
23592 NK_API int | |
23593 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, | |
23594 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) | |
23595 { | |
23596 struct nk_window *win; | |
23597 struct nk_rect header; | |
23598 const struct nk_input *in; | |
23599 int is_clicked = nk_false; | |
23600 nk_flags state; | |
23601 | |
23602 NK_ASSERT(ctx); | |
23603 NK_ASSERT(ctx->current); | |
23604 NK_ASSERT(ctx->current->layout); | |
23605 if (!ctx || !ctx->current || !ctx->current->layout) | |
23606 return 0; | |
23607 | |
23608 win = ctx->current; | |
23609 state = nk_widget(&header, ctx); | |
23610 if (!state) return 0; | |
23611 | |
23612 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; | |
23613 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, | |
23614 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, | |
23615 ctx->style.font, in)) is_clicked = nk_true; | |
23616 return nk_menu_begin(ctx, win, title, is_clicked, header, size); | |
23617 } | |
23618 | |
23619 NK_API int nk_menu_begin_symbol_label(struct nk_context *ctx, | |
23620 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) | |
23621 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);} | |
23622 | |
23623 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) | |
23624 {return nk_contextual_item_text(ctx, title, len, align);} | |
23625 | |
23626 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) | |
23627 {return nk_contextual_item_label(ctx, label, align);} | |
23628 | |
23629 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, | |
23630 const char *label, nk_flags align) | |
23631 {return nk_contextual_item_image_label(ctx, img, label, align);} | |
23632 | |
23633 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, | |
23634 const char *text, int len, nk_flags align) | |
23635 {return nk_contextual_item_image_text(ctx, img, text, len, align);} | |
23636 | |
23637 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, | |
23638 const char *text, int len, nk_flags align) | |
23639 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);} | |
23640 | |
23641 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, | |
23642 const char *label, nk_flags align) | |
23643 {return nk_contextual_item_symbol_label(ctx, sym, label, align);} | |
23644 | |
23645 NK_API void nk_menu_close(struct nk_context *ctx) | |
23646 {nk_contextual_close(ctx);} | |
23647 | |
23648 NK_API void | |
23649 nk_menu_end(struct nk_context *ctx) | |
23650 {nk_contextual_end(ctx);} | |
23651 | |
23652 #endif /* NK_IMPLEMENTATION */ |