Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
nuklear_property.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ===============================================================
5 *
6 * PROPERTY
7 *
8 * ===============================================================*/
9NK_LIB void
10nk_drag_behavior(nk_flags *state, const struct nk_input *in,
11 struct nk_rect drag, struct nk_property_variant *variant,
12 float inc_per_pixel)
13{
14 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
15 int left_mouse_click_in_cursor = in &&
16 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true);
17
18 nk_widget_state_reset(state);
19 if (nk_input_is_mouse_hovering_rect(in, drag))
21
22 if (left_mouse_down && left_mouse_click_in_cursor) {
23 float delta, pixels;
24 pixels = in->mouse.delta.x;
25 delta = pixels * inc_per_pixel;
26 switch (variant->kind) {
27 default: break;
28 case NK_PROPERTY_INT:
29 variant->value.i = variant->value.i + (int)delta;
30 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
31 break;
32 case NK_PROPERTY_FLOAT:
33 variant->value.f = variant->value.f + (float)delta;
34 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
35 break;
36 case NK_PROPERTY_DOUBLE:
37 variant->value.d = variant->value.d + (double)delta;
38 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
39 break;
40 }
42 }
43 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
45 else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
46 *state |= NK_WIDGET_STATE_LEFT;
47}
48NK_LIB void
49nk_property_behavior(nk_flags *ws, const struct nk_input *in,
50 struct nk_rect property, struct nk_rect label, struct nk_rect edit,
51 struct nk_rect empty, int *state, struct nk_property_variant *variant,
52 float inc_per_pixel)
53{
54 nk_widget_state_reset(ws);
55 if (in && *state == NK_PROPERTY_DEFAULT) {
56 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
57 *state = NK_PROPERTY_EDIT;
58 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true))
59 *state = NK_PROPERTY_DRAG;
60 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true))
61 *state = NK_PROPERTY_DRAG;
62 }
63 if (*state == NK_PROPERTY_DRAG) {
64 nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
65 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
66 }
67}
68NK_LIB void
69nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
70 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
71 const char *name, int len, const struct nk_user_font *font)
72{
73 struct nk_text text;
74 const struct nk_style_item *background;
75
76 /* select correct background and text color */
77 if (state & NK_WIDGET_STATE_ACTIVED) {
78 background = &style->active;
79 text.text = style->label_active;
80 } else if (state & NK_WIDGET_STATE_HOVER) {
81 background = &style->hover;
82 text.text = style->label_hover;
83 } else {
84 background = &style->normal;
85 text.text = style->label_normal;
86 }
87
88 text.text = nk_rgb_factor(text.text, style->color_factor);
89
90 /* draw background */
91 switch(background->type) {
92 case NK_STYLE_ITEM_IMAGE:
93 text.background = nk_rgba(0, 0, 0, 0);
94 nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
95 break;
96 case NK_STYLE_ITEM_NINE_SLICE:
97 text.background = nk_rgba(0, 0, 0, 0);
98 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
99 break;
100 case NK_STYLE_ITEM_COLOR:
101 text.background = background->data.color;
102 nk_fill_rect(out, *bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
103 nk_stroke_rect(out, *bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
104 break;
105 }
106
107 /* draw label */
108 text.padding = nk_vec2(0,0);
109 if (name && name[0] != '#') {
110 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
111 }
112}
113NK_INTERN void
114nk_property_save(struct nk_property_variant *variant, char *buffer, int len)
115{
116 buffer[len] = '\0';
117 switch (variant->kind) {
118 default: break;
119 case NK_PROPERTY_INT:
120 variant->value.i = nk_strtoi(buffer, 0);
121 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
122 break;
123 case NK_PROPERTY_FLOAT:
124 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
125 variant->value.f = nk_strtof(buffer, 0);
126 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
127 break;
128 case NK_PROPERTY_DOUBLE:
129 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
130 variant->value.d = NK_STRTOD(buffer, 0);
131 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
132 break;
133 }
134}
135NK_LIB void
136nk_do_property(nk_flags *ws,
137 struct nk_command_buffer *out, struct nk_rect property,
138 const char *name, struct nk_property_variant *variant,
139 float inc_per_pixel, char *buffer, int *len,
140 int *state, int *cursor, int *select_begin, int *select_end,
141 const struct nk_style_property *style,
142 enum nk_property_filter filter, struct nk_input *in,
143 const struct nk_user_font *font, struct nk_text_edit *text_edit,
144 enum nk_button_behavior behavior)
145{
146 const nk_plugin_filter filters[] = {
147 nk_filter_decimal,
148 nk_filter_float
149 };
150 nk_bool active, old;
151 int num_len = 0, name_len = 0;
152 char string[NK_MAX_NUMBER_BUFFER];
153 float size;
154
155 char *dst = 0;
156 int *length;
157
158 struct nk_rect left;
159 struct nk_rect right;
160 struct nk_rect label;
161 struct nk_rect edit;
162 struct nk_rect empty;
163
164 /* left decrement button */
165 left.h = font->height/2;
166 left.w = left.h;
167 left.x = property.x + style->border + style->padding.x;
168 left.y = property.y + style->border + property.h/2.0f - left.h/2;
169
170 /* text label */
171 if (name && name[0] != '#') {
172 name_len = nk_strlen(name);
173 }
174 size = font->width(font->userdata, font->height, name, name_len);
175 label.x = left.x + left.w + style->padding.x;
176 label.w = (float)size + 2 * style->padding.x;
177 label.y = property.y + style->border + style->padding.y;
178 label.h = property.h - (2 * style->border + 2 * style->padding.y);
179
180 /* right increment button */
181 right.y = left.y;
182 right.w = left.w;
183 right.h = left.h;
184 right.x = property.x + property.w - (right.w + style->padding.x);
185
186 /* edit */
187 if (*state == NK_PROPERTY_EDIT) {
188 size = font->width(font->userdata, font->height, buffer, *len);
189 size += style->edit.cursor_size;
190 length = len;
191 dst = buffer;
192 } else {
193 switch (variant->kind) {
194 default: break;
195 case NK_PROPERTY_INT:
196 nk_itoa(string, variant->value.i);
197 num_len = nk_strlen(string);
198 break;
199 case NK_PROPERTY_FLOAT:
200 NK_DTOA(string, (double)variant->value.f);
201 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
202 break;
203 case NK_PROPERTY_DOUBLE:
204 NK_DTOA(string, variant->value.d);
205 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
206 break;
207 }
208 size = font->width(font->userdata, font->height, string, num_len);
209 dst = string;
210 length = &num_len;
211 }
212
213 edit.w = (float)size + 2 * style->padding.x;
214 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
215 edit.x = right.x - (edit.w + style->padding.x);
216 edit.y = property.y + style->border;
217 edit.h = property.h - (2 * style->border);
218
219 /* empty left space activator */
220 empty.w = edit.x - (label.x + label.w);
221 empty.x = label.x + label.w;
222 empty.y = property.y;
223 empty.h = property.h;
224
225 /* update property */
226 old = (*state == NK_PROPERTY_EDIT);
227 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
228
229 /* draw property */
230 if (style->draw_begin) style->draw_begin(out, style->userdata);
231 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
232 if (style->draw_end) style->draw_end(out, style->userdata);
233
234 /* execute right button */
235 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
236 switch (variant->kind) {
237 default: break;
238 case NK_PROPERTY_INT:
239 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
240 case NK_PROPERTY_FLOAT:
241 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
242 case NK_PROPERTY_DOUBLE:
243 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
244 }
245 }
246 /* execute left button */
247 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
248 switch (variant->kind) {
249 default: break;
250 case NK_PROPERTY_INT:
251 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
252 case NK_PROPERTY_FLOAT:
253 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
254 case NK_PROPERTY_DOUBLE:
255 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
256 }
257 }
258 if (!old && (*state == NK_PROPERTY_EDIT)) {
259 /* property has been activated so setup buffer */
260 NK_MEMCPY(buffer, dst, (nk_size)*length);
261 *cursor = nk_utf_len(buffer, *length);
262 *len = *length;
263 length = len;
264 dst = buffer;
265 active = 0;
266 } else active = (*state == NK_PROPERTY_EDIT);
267
268 /* execute and run text edit field */
269 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
270 text_edit->active = (unsigned char)active;
271 text_edit->string.len = *length;
272 text_edit->cursor = NK_CLAMP(0, *cursor, *length);
273 text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
274 text_edit->select_end = NK_CLAMP(0,*select_end, *length);
275 text_edit->string.buffer.allocated = (nk_size)*length;
276 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER;
277 text_edit->string.buffer.memory.ptr = dst;
278 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
279 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
280 nk_do_edit(ws, out, edit, (int)NK_EDIT_FIELD|(int)NK_EDIT_AUTO_SELECT,
281 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
282
283 *length = text_edit->string.len;
284 *cursor = text_edit->cursor;
285 *select_begin = text_edit->select_start;
286 *select_end = text_edit->select_end;
287 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
288 text_edit->active = nk_false;
289
290 if (active && !text_edit->active) {
291 /* property is now not active so convert edit text to value*/
292 *state = NK_PROPERTY_DEFAULT;
293 nk_property_save(variant, buffer, *len);
294 }
295}
296NK_LIB struct nk_property_variant
297nk_property_variant_int(int value, int min_value, int max_value, int step)
298{
299 struct nk_property_variant result;
300 result.kind = NK_PROPERTY_INT;
301 result.value.i = value;
302 result.min_value.i = min_value;
303 result.max_value.i = max_value;
304 result.step.i = step;
305 return result;
306}
307NK_LIB struct nk_property_variant
308nk_property_variant_float(float value, float min_value, float max_value, float step)
309{
310 struct nk_property_variant result;
311 result.kind = NK_PROPERTY_FLOAT;
312 result.value.f = value;
313 result.min_value.f = min_value;
314 result.max_value.f = max_value;
315 result.step.f = step;
316 return result;
317}
318NK_LIB struct nk_property_variant
319nk_property_variant_double(double value, double min_value, double max_value,
320 double step)
321{
322 struct nk_property_variant result;
323 result.kind = NK_PROPERTY_DOUBLE;
324 result.value.d = value;
325 result.min_value.d = min_value;
326 result.max_value.d = max_value;
327 result.step.d = step;
328 return result;
329}
330NK_LIB void
331nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
332 float inc_per_pixel, const enum nk_property_filter filter)
333{
334 struct nk_window *win;
335 struct nk_panel *layout;
336 struct nk_input *in;
337 const struct nk_style *style;
338
339 struct nk_rect bounds;
341 nk_bool hot;
342
343 int *state = 0;
344 nk_hash hash = 0;
345 char *buffer = 0;
346 int *len = 0;
347 int *cursor = 0;
348 int *select_begin = 0;
349 int *select_end = 0;
350 int old_state;
351 int prev_state;
352
353 char dummy_buffer[NK_MAX_NUMBER_BUFFER];
354 int dummy_state = NK_PROPERTY_DEFAULT;
355 int dummy_length = 0;
356 int dummy_cursor = 0;
357 int dummy_select_begin = 0;
358 int dummy_select_end = 0;
359
360 NK_ASSERT(ctx);
361 NK_ASSERT(ctx->current);
362 NK_ASSERT(ctx->current->layout);
363 if (!ctx || !ctx->current || !ctx->current->layout)
364 return;
365
366 win = ctx->current;
367 layout = win->layout;
368 style = &ctx->style;
369 s = nk_widget(&bounds, ctx);
370 if (!s) return;
371
372 /* calculate hash from name */
373 if (name[0] == '#') {
374 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
375 name++; /* special number hash */
376 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
377
378 /* check if property is previously hot */
379 if (win->property.prev_state == NK_PROPERTY_EDIT && hash == win->property.prev_name) {
380 nk_property_save(variant, win->property.prev_buffer, win->property.prev_length);
381 win->property.prev_state = NK_PROPERTY_DEFAULT;
382 }
383
384 /* check if property is currently hot item */
385 hot = win->property.active && hash == win->property.name;
386 if (hot) {
387 buffer = win->property.buffer;
388 len = &win->property.length;
389 cursor = &win->property.cursor;
390 state = &win->property.state;
391 select_begin = &win->property.select_start;
392 select_end = &win->property.select_end;
393 } else {
394 buffer = dummy_buffer;
395 len = &dummy_length;
396 cursor = &dummy_cursor;
397 state = &dummy_state;
398 select_begin = &dummy_select_begin;
399 select_end = &dummy_select_end;
400 }
401
402 /* execute property widget */
403 old_state = *state;
404 prev_state = win->property.state;
405 ctx->text_edit.clip = ctx->clip;
406 in = ((s == NK_WIDGET_ROM && !win->property.active) ||
407 layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_DISABLED) ? 0 : &ctx->input;
408 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
409 variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
410 select_end, &style->property, filter, in, style->font, &ctx->text_edit,
411 ctx->button_behavior);
412
413 if (in && *state != NK_PROPERTY_DEFAULT && !hot) {
414 /* another property was active */
415 if (win->property.active /* && hash != win->property.name */) {
416 win->property.prev_state = prev_state;
417 win->property.prev_name = win->property.name;
418 win->property.prev_length = win->property.length;
419 NK_MEMCPY(win->property.prev_buffer, win->property.buffer, win->property.length);
420 }
421 /* current property is now hot */
422 win->property.active = 1;
423 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
424 win->property.length = *len;
425 win->property.cursor = *cursor;
426 win->property.state = *state;
427 win->property.name = hash;
428 win->property.select_start = *select_begin;
429 win->property.select_end = *select_end;
430 win->edit.active = nk_true;
431 if (*state == NK_PROPERTY_DRAG) {
432 ctx->input.mouse.grab = nk_true;
433 ctx->input.mouse.grabbed = nk_true;
434 }
435 }
436 /* check if previously active property is now inactive */
437 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
438 if (old_state == NK_PROPERTY_DRAG) {
439 ctx->input.mouse.grab = nk_false;
440 ctx->input.mouse.grabbed = nk_false;
441 ctx->input.mouse.ungrab = nk_true;
442 }
443 win->property.select_start = 0;
444 win->property.select_end = 0;
445 win->property.active = 0;
446 win->edit.active = nk_false;
447 }
448}
449NK_API void
450nk_property_int(struct nk_context *ctx, const char *name,
451 int min, int *val, int max, int step, float inc_per_pixel)
452{
453 struct nk_property_variant variant;
454 NK_ASSERT(ctx);
455 NK_ASSERT(name);
456 NK_ASSERT(val);
457
458 if (!ctx || !ctx->current || !name || !val) return;
459 variant = nk_property_variant_int(*val, min, max, step);
460 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
461 *val = variant.value.i;
462}
463NK_API void
464nk_property_float(struct nk_context *ctx, const char *name,
465 float min, float *val, float max, float step, float inc_per_pixel)
466{
467 struct nk_property_variant variant;
468 NK_ASSERT(ctx);
469 NK_ASSERT(name);
470 NK_ASSERT(val);
471
472 if (!ctx || !ctx->current || !name || !val) return;
473 variant = nk_property_variant_float(*val, min, max, step);
474 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
475 *val = variant.value.f;
476}
477NK_API void
478nk_property_double(struct nk_context *ctx, const char *name,
479 double min, double *val, double max, double step, float inc_per_pixel)
480{
481 struct nk_property_variant variant;
482 NK_ASSERT(ctx);
483 NK_ASSERT(name);
484 NK_ASSERT(val);
485
486 if (!ctx || !ctx->current || !name || !val) return;
487 variant = nk_property_variant_double(*val, min, max, step);
488 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
489 *val = variant.value.d;
490}
491NK_API int
492nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
493 int max, int step, float inc_per_pixel)
494{
495 struct nk_property_variant variant;
496 NK_ASSERT(ctx);
497 NK_ASSERT(name);
498
499 if (!ctx || !ctx->current || !name) return val;
500 variant = nk_property_variant_int(val, min, max, step);
501 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
502 val = variant.value.i;
503 return val;
504}
505NK_API float
506nk_propertyf(struct nk_context *ctx, const char *name, float min,
507 float val, float max, float step, float inc_per_pixel)
508{
509 struct nk_property_variant variant;
510 NK_ASSERT(ctx);
511 NK_ASSERT(name);
512
513 if (!ctx || !ctx->current || !name) return val;
514 variant = nk_property_variant_float(val, min, max, step);
515 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
516 val = variant.value.f;
517 return val;
518}
519NK_API double
520nk_propertyd(struct nk_context *ctx, const char *name, double min,
521 double val, double max, double step, float inc_per_pixel)
522{
523 struct nk_property_variant variant;
524 NK_ASSERT(ctx);
525 NK_ASSERT(name);
526
527 if (!ctx || !ctx->current || !name) return val;
528 variant = nk_property_variant_double(val, min, max, step);
529 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
530 val = variant.value.d;
531 return val;
532}
533
main API and documentation file
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
Definition nuklear.h:5509
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
filled shades
@ NK_WIDGET_STATE_LEFT
!< widget is currently activated
Definition nuklear.h:3108
@ NK_WIDGET_STATE_ACTIVED
!< widget is being hovered
Definition nuklear.h:3107
@ NK_WIDGET_STATE_ENTERED
!< widget is neither active nor hovered
Definition nuklear.h:3105
@ NK_WIDGET_STATE_HOVER
!< widget has been hovered on the current frame
Definition nuklear.h:3106
@ NK_WIDGET_STATE_ACTIVE
!< widget is being hovered
Definition nuklear.h:3110
@ NK_WIDGET_STATE_HOVERED
!< widget is from this frame on not hovered anymore
Definition nuklear.h:3109
nk_widget_layout_states
Definition nuklear.h:3096
@ NK_WIDGET_DISABLED
The widget is manually disabled and acts like NK_WIDGET_ROM.
Definition nuklear.h:3100
@ NK_WIDGET_ROM
The widget is partially visible and cannot be updated.
Definition nuklear.h:3099
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
struct nk_memory memory
!< memory management type
Definition nuklear.h:4209
nk_size size
!< number of allocation calls
Definition nuklear.h:4214
nk_size allocated
!< growing factor for dynamic memory management
Definition nuklear.h:4211
struct nk_text_edit text_edit
text editor objects are quite big because of an internal undo/redo stack.
Definition nuklear.h:5748
nk_text_width_f width
!< max height of the font
Definition nuklear.h:4025
float height
!< user provided font handle
Definition nuklear.h:4024