forked from rgriege/Violet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gui.h
9004 lines (7868 loc) · 248 KB
/
gui.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef VIOLET_GUI_H
#define VIOLET_GUI_H
#include "violet/core.h"
#include "violet/color.h"
#include "violet/key.h"
/* Texture */
typedef enum gui_blend
{
GUI_BLEND_NRM,
GUI_BLEND_ADD,
GUI_BLEND_MUL,
GUI_BLEND__COUNT,
} gui_blend_e;
typedef struct gui_texture
{
u32 handle;
u32 width;
u32 height;
u32 blend;
} gui_texture_t;
m3f gui_texture_get_transform(const gui_texture_t *texture, s32 x, s32 y,
r32 sx, r32 sy, r32 rotation);
/* Image */
typedef struct gui_texture gui_img_t;
/* Font */
typedef enum gui_align
{
GUI_ALIGN_LEFT = 0x01,
GUI_ALIGN_CENTER = 0x02,
GUI_ALIGN_RIGHT = 0x04,
GUI_ALIGN_TOP = 0x10,
GUI_ALIGN_MIDDLE = 0x20,
GUI_ALIGN_BOTTOM = 0x40,
GUI_ALIGN_TOPLEFT = GUI_ALIGN_TOP | GUI_ALIGN_LEFT,
GUI_ALIGN_MIDLEFT = GUI_ALIGN_MIDDLE | GUI_ALIGN_LEFT,
GUI_ALIGN_BOTLEFT = GUI_ALIGN_BOTTOM | GUI_ALIGN_LEFT,
GUI_ALIGN_TOPCENTER = GUI_ALIGN_TOP | GUI_ALIGN_CENTER,
GUI_ALIGN_MIDCENTER = GUI_ALIGN_MIDDLE | GUI_ALIGN_CENTER,
GUI_ALIGN_BOTCENTER = GUI_ALIGN_BOTTOM | GUI_ALIGN_CENTER,
GUI_ALIGN_TOPRIGHT = GUI_ALIGN_TOP | GUI_ALIGN_RIGHT,
GUI_ALIGN_MIDRIGHT = GUI_ALIGN_MIDDLE | GUI_ALIGN_RIGHT,
GUI_ALIGN_BOTRIGHT = GUI_ALIGN_BOTTOM | GUI_ALIGN_RIGHT,
} gui_align_e;
#define GUI_ALIGN_VERTICAL (GUI_ALIGN_TOP | GUI_ALIGN_MIDDLE | GUI_ALIGN_BOTTOM)
#define GUI_ALIGN_HORIZONTAL (GUI_ALIGN_LEFT | GUI_ALIGN_CENTER | GUI_ALIGN_RIGHT)
void gui_align_anchor(s32 x, s32 y, s32 w, s32 h, gui_align_e align, s32 *px, s32 *py);
typedef struct gui_font_metrics
{
s32 ascent, descent, line_gap, newline_dist;
} gui_font_metrics_t;
typedef struct gui_char_quad
{
gui_texture_t texture;
r32 x0, y0, s0, t0;
r32 x1, y1, s1, t1;
r32 advance;
} gui_char_quad_t;
typedef void*(*gui_font_f)(void *handle, const char *path, s32 size);
typedef b32(*gui_font_metrics_f)(void *font, gui_font_metrics_t *metrics);
typedef b32(*gui_char_quad_f)(void *font, s32 codepoint, r32 x, r32 y, gui_char_quad_t *quad);
typedef struct gui_fonts
{
void *handle;
gui_font_f get_font;
gui_font_metrics_f get_metrics;
gui_char_quad_f get_char_quad;
} gui_fonts_t;
/* General Gui */
typedef struct gui gui_t;
typedef enum gui_cursor
{
GUI_CURSOR_DEFAULT,
GUI_CURSOR_RESIZE_NS,
GUI_CURSOR_RESIZE_EW,
GUI_CURSOR_TEXT_INPUT,
GUI_CURSOR_BUTTON,
GUI_CURSOR_COUNT
} gui_cursor_e;
gui_t *gui_create(s32 w, s32 h, u32 texture_white, u32 texture_white_dotted,
gui_fonts_t fonts, const char *font_file_path);
void gui_destroy(gui_t *gui);
void gui_dim(const gui_t *gui, s32 *x, s32 *y);
void gui_begin_frame(gui_t *gui);
void gui_end_frame(gui_t *gui);
void gui_end_frame_ex(gui_t *gui, u32 target_frame_milli,
u32 idle_frame_milli, u32 idle_start_milli);
#ifndef GUI_CLIPBOARD_SIZE
#define GUI_CLIPBOARD_SIZE 64
#endif
b32 gui_text_input_active(const gui_t *gui);
b32 gui_has_clipboard_text(const gui_t *gui);
void gui_get_clipboard_text(const gui_t *gui, char *text);
u32 gui_cursor(const gui_t *gui);
void gui_set_cursor(gui_t *gui, gui_cursor_e cursor);
void *gui_window(gui_t *gui);
void gui_set_window(gui_t *gui, void *window);
void gui_set_drag_height(gui_t *gui, s32 h);
timepoint_t gui_frame_start(const gui_t *gui);
u32 gui_frame_time_milli(const gui_t *gui);
u32 gui_run_time_milli(const gui_t *gui);
timepoint_t gui_last_input_time(const gui_t *gui);
typedef enum gui_mouse_button
{
MB_LEFT = 1 << 0,
MB_MIDDLE = 1 << 1,
MB_RIGHT = 1 << 2,
MB_X1 = 1 << 3,
MB_X2 = 1 << 4,
MB_WHEELUP = 1 << 5,
MB_WHEELDOWN = 1 << 6,
MB_WHEEL = MB_WHEELUP | MB_WHEELDOWN,
} gui_mouse_button_e;
/* Input */
void gui_events_begin(gui_t *gui);
void gui_event_add_update(gui_t *gui);
void gui_event_set_mouse_pos(gui_t *gui, s32 x, s32 y);
void gui_event_set_mouse_btn(gui_t *gui, gui_mouse_button_e button);
void gui_event_add_text_input(gui_t *gui, const char *text);
void gui_event_set_keyboard(gui_t *gui, const u8 *keys, u32 key_cnt);
void gui_event_add_clipboard(gui_t *gui, const char *text);
void gui_event_add_window_leave(gui_t *gui);
void gui_event_set_window_dim(gui_t *gui, s32 w, s32 h);
void gui_events_end(gui_t *gui);
#ifndef GUI_MOUSE_DOUBLE_CLICK_DIST
#define GUI_MOUSE_DOUBLE_CLICK_DIST 5
#endif
#ifndef GUI_MOUSE_DOUBLE_CLICK_INTERVAL
#define GUI_MOUSE_DOUBLE_CLICK_INTERVAL 500 /* windows default */
#endif
void mouse_pos(const gui_t *gui, s32 *x, s32 *y);
void mouse_pos_last(const gui_t *gui, s32 *x, s32 *y);
void mouse_pos_press(const gui_t *gui, s32 *x, s32 *y);
b32 mouse_pos_changed(const gui_t *gui);
void mouse_pos_delta(const gui_t *gui, s32 *x, s32 *y);
b32 mouse_pressed(const gui_t *gui, u32 mask);
b32 mouse_pressed_bg(const gui_t *gui, u32 mask);
b32 mouse_down(const gui_t *gui, u32 mask);
b32 mouse_down_bg(const gui_t *gui, u32 mask);
b32 mouse_released(const gui_t *gui, u32 mask);
b32 mouse_released_bg(const gui_t *gui, u32 mask);
b32 mouse_covered(const gui_t *gui);
b32 mouse_over_box(const gui_t *gui, box2i box);
b32 mouse_over_xywh(const gui_t *gui, s32 x, s32 y, s32 w, s32 h);
b32 mouse_covered_by_any_popup(const gui_t *gui);
void mouse_cover(gui_t *gui, u64 widget_id);
b32 mouse_over_bg(const gui_t *gui);
/* use in conjunction with mouse_pressed or mouse_released */
b32 mouse_double(const gui_t *gui, u32 mask);
b32 mouse_scroll(const gui_t *gui, s32 *dir);
b32 mouse_scroll_bg(const gui_t *gui, s32 *dir);
void mouse_press_debug(gui_t *gui, b32 enabled);
b32 key_down(const gui_t *gui, gui_key_t key);
b32 key_down_any(const gui_t *gui);
b32 key_pressed(const gui_t *gui, gui_key_t key);
b32 key_pressed_any(const gui_t *gui);
b32 key_released(const gui_t *gui, gui_key_t key);
b32 key_released_any(const gui_t *gui);
b32 key_mod(const gui_t *gui, gui_key_mod_t mod);
b32 key_toggled(const gui_t *gui, gui_key_toggle_t toggle);
const u8 *keyboard_state(const gui_t *gui);
/* Direct write access to vertex buffers */
typedef enum gui_draw_call_type
{
GUI_DRAW_POINTS,
GUI_DRAW_LINE_STRIP,
GUI_DRAW_LINE_LOOP,
GUI_DRAW_LINES,
GUI_DRAW_TRIANGLE_STRIP,
GUI_DRAW_TRIANGLE_FAN,
GUI_DRAW_TRIANGLES,
GUI_DRAW_QUAD_STRIP,
GUI_DRAW_QUADS,
GUI_DRAW_POLYGON,
GUI_DRAW_COUNT
} gui_draw_call_type_e;
b32 gui_begin(gui_t *gui, u32 num_verts, gui_draw_call_type_e type);
b32 gui_begin_tex(gui_t *gui, u32 num_verts, gui_draw_call_type_e type,
u32 tex, gui_blend_e blend);
void gui_vertf(gui_t *gui, r32 x, r32 y, color_t c, r32 u, r32 v);
void gui_end(gui_t *gui);
/* Primitives */
typedef enum gui_img_scale
{
GUI_IMG_SCALED,
GUI_IMG_CENTERED,
} gui_img_scale_e;
void gui_line(gui_t *gui, s32 x0, s32 y0, s32 x1, s32 y1, s32 w, color_t c);
void gui_linef(gui_t *gui, r32 x0, r32 y0, r32 x1, r32 y1, r32 w, color_t c);
void gui_tri(gui_t *gui, s32 x0, s32 y0, s32 x1, s32 y1, s32 x2, s32 y2,
color_t fill, color_t stroke);
void gui_rect(gui_t *gui, s32 x, s32 y, s32 w, s32 h, color_t fill, color_t stroke);
void gui_rect_mcolor(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
color_t bl, color_t br, color_t tr, color_t tl);
void gui_rect_dropshadow(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
s32 offset, s32 thickness, color_t color);
void gui_circ(gui_t *gui, s32 x, s32 y, s32 r, color_t fill, color_t stroke);
void gui_arc(gui_t *gui, s32 x, s32 y, r32 r, r32 angle_start, r32 angle_end,
color_t fill, color_t stroke);
void gui_trisf(gui_t *gui, const v2f *v, u32 n, color_t fill);
void gui_poly(gui_t *gui, const v2i *v, u32 n, color_t fill, color_t stroke);
void gui_polyf(gui_t *gui, const v2f *v, u32 n, color_t fill, color_t stroke);
void gui_polyline(gui_t *gui, const v2i *v, u32 n, color_t stroke);
void gui_polylinef(gui_t *gui, const v2f *v, u32 n, r32 w, color_t stroke);
void gui_img(gui_t *gui, s32 x, s32 y, const gui_img_t *img);
void gui_img_ex(gui_t *gui, s32 x, s32 y, const gui_img_t *img, r32 sx, r32 sy,
r32 rotation, r32 opacity);
void gui_img_boxed(gui_t *gui, s32 x, s32 y, s32 w, s32 h, const gui_img_t *img,
gui_img_scale_e scale);
void gui_txt(gui_t *gui, s32 x, s32 y, s32 size, const char *txt, color_t c,
gui_align_e align);
void gui_txt_ex(gui_t *gui, s32 x, s32 y, s32 size, const char *txt,
color_t c, gui_align_e align, r32 rotation);
void gui_txt_dim(const gui_t *gui, s32 x, s32 y, s32 size, const char *txt,
gui_align_e align, s32 *px, s32 *py, s32 *pw, s32 *ph);
s32 gui_txt_width(const gui_t *gui, const char *txt, s32 size);
gui_fonts_t gui_get_fonts(const gui_t *gui);
void gui_mask_push(gui_t *gui, s32 x, s32 y, s32 w, s32 h);
void gui_mask_pop(gui_t *gui);
void gui_hint_render(gui_t *gui, u64 id, const char *hint);
typedef struct gui_line_style gui_line_style_t;
typedef struct gui_text_style gui_text_style_t;
typedef struct gui_element_style gui_element_style_t;
void gui_line_styled(gui_t *gui, s32 x0, s32 y0, s32 x1, s32 y1,
const gui_line_style_t *style);
void gui_txt_styled(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const char *txt, const gui_text_style_t *style);
u32 gui_wrap_txt(const gui_t *gui, char *txt, s32 padding, s32 size, r32 max_width);
typedef void(*gui_pen_t)(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_null(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_rect(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_circ(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
b32 gui_point_visible(const gui_t *gui, s32 x, s32 y);
b32 gui_box_visible(const gui_t *gui, s32 x, s32 y, s32 w, s32 h);
/* Render buffer */
typedef struct gui_draw_call
{
u32 idx;
u32 cnt;
u32 type;
u32 tex;
u32 blend;
} gui_draw_call_t;
typedef struct gui_layer
{
u32 draw_call_idx, draw_call_cnt;
s32 x, y, w, h;
s32 pri;
} gui_layer_t;
typedef struct gui_render_output
{
u32 num_layers;
const gui_layer_t *layers;
u32 num_verts;
struct {
const v2f *pos;
const color_t *color;
const v2f *tex_coord;
} verts;
u32 num_draw_calls;
const gui_draw_call_t *draw_calls;
} gui_render_output_t;
u32 gui_num_layers(const gui_t *gui);
u32 gui_vert_cnt(const gui_t *gui);
u32 gui_draw_call_cnt(const gui_t *gui);
u32 gui_culled_vert_cnt(const gui_t *gui);
u32 gui_culled_draw_call_cnt(const gui_t *gui);
u32 gui_culled_widget_cnt(const gui_t *gui);
void gui_get_render_output(const gui_t *gui, gui_render_output_t *output);
/* Widgets */
/* Limit for input boxes & dropdowns */
#ifndef GUI_TXT_MAX_LENGTH
#define GUI_TXT_MAX_LENGTH 128
#endif
#ifndef GUI_POPUP_STACK_SIZE
#define GUI_POPUP_STACK_SIZE 2
#endif
#define GUI_FOCUS_STACK_SIZE (GUI_POPUP_STACK_SIZE + 1)
#ifndef GUI_HINT_TIMER
#define GUI_HINT_TIMER 1000
#endif
#define GUI_MIN_CUSTOM_BASE_ID (1 << 16)
typedef enum gui_npt_flags
{
GUI_NPT_PASSWORD = 1 << 0,
GUI_NPT_MULTILINE = 1 << 1,
GUI_NPT_SELECT_ON_FOCUS = 1 << 2,
GUI_NPT_COMPLETE_ON_ENTER = 1 << 3, /* always enabled */
GUI_NPT_COMPLETE_ON_TAB = 1 << 4,
GUI_NPT_COMPLETE_ON_CLICK_OUT = 1 << 5,
GUI_NPT_COMPLETE_ON_ESCAPE = 1 << 6,
GUI_NPT_COMPLETE_ON_DEFOCUS = GUI_NPT_COMPLETE_ON_TAB
| GUI_NPT_COMPLETE_ON_CLICK_OUT
| GUI_NPT_COMPLETE_ON_ESCAPE,
} gui_npt_flags_e;
typedef struct gui_npt_filter
{
b8 ascii[127];
b8 non_ascii;
} gui_npt_filter_t;
typedef const gui_npt_filter_t* gui_npt_filter_p;
typedef enum gui_btn_val
{
GUI_BTN_NONE,
GUI_BTN_PRESS,
GUI_BTN_HOLD,
} gui_btn_e;
extern const gui_npt_filter_t g_gui_npt_filter_print;
extern const gui_npt_filter_t g_gui_npt_filter_print_multiline;
extern const gui_npt_filter_t g_gui_npt_filter_numeric;
extern const gui_npt_filter_t g_gui_npt_filter_hex;
b32 gui_npt_filter(gui_npt_filter_p filter, s32 codepoint);
const char *gui_npt_val_buf(const gui_t *gui);
char *gui_npt_val_buf_mut(gui_t *gui);
void gui_npt_val_buf_clear(gui_t *gui);
typedef struct gui_widget_bounds
{
box2i bbox;
box2i children;
struct gui_widget_bounds *prev;
} gui_widget_bounds_t;
void gui_widget_bounds_push(gui_t *gui, gui_widget_bounds_t *bounds, b32 propogate);
void gui_widget_bounds_pop(gui_t *gui, gui_widget_bounds_t *bounds, b32 propogate);
void gui_widget_bounds_extend(gui_t *gui, s32 x, s32 y, s32 w, s32 h);
void gui_widget_bounds_get(const gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
typedef struct gui_scroll_area
{
v2i pos;
v2i dim;
v2i scroll;
gui_widget_bounds_t widget_bounds;
box2i last_children_bbox;
struct gui_scroll_area *prev;
} gui_scroll_area_t;
/* returns GUI_NPT_COMPLETE_ON_XXX if completed using an enabled completion method
* or 0 otherwise */
s32 gui_npt_txt(gui_t *gui, s32 x, s32 y, s32 w, s32 h, char *txt, u32 n,
const char *hint, gui_npt_flags_e flags);
s32 gui_npt_txt_ex(gui_t *gui, s32 x, s32 y, s32 w, s32 h, char *txt, u32 n,
const char *hint, gui_npt_flags_e flags, gui_npt_filter_p filter);
s32 gui_npt_txt_invis(gui_t *gui, s32 x, s32 y, char *txt, u32 n, gui_npt_filter_p filter);
s32 gui_npt_val(gui_t *gui, s32 x, s32 y, s32 w, s32 h, const char *txt, u32 n,
gui_npt_flags_e flags, gui_npt_filter_p filter);
gui_btn_e gui_btn_logic(gui_t *gui, u64 id, gui_mouse_button_e mb, b32 contains_mouse);
s32 gui_btn_txt(gui_t *gui, s32 x, s32 y, s32 w, s32 h, const char *txt);
s32 gui_btn_img(gui_t *gui, s32 x, s32 y, s32 w, s32 h, const gui_img_t *img,
gui_img_scale_e scale);
s32 gui_btn_pen(gui_t *gui, s32 x, s32 y, s32 w, s32 h, gui_pen_t pen);
s32 gui_btn_color(gui_t *gui, s32 x, s32 y, s32 w, s32 h, color_t color);
b32 gui_chk(gui_t *gui, s32 x, s32 y, s32 w, s32 h, const char *txt, b32 *val);
b32 gui_chk_pen(gui_t *gui, s32 x, s32 y, s32 w, s32 h, gui_pen_t pen, b32 *val);
b32 gui_slider_x(gui_t *gui, s32 x, s32 y, s32 w, s32 h, r32 *val);
b32 gui_slider_y(gui_t *gui, s32 x, s32 y, s32 w, s32 h, r32 *val);
b32 gui_range_x(gui_t *gui, s32 x, s32 y, s32 w, s32 h, r32 *val,
r32 min, r32 max);
b32 gui_range_y(gui_t *gui, s32 x, s32 y, s32 w, s32 h, r32 *val,
r32 min, r32 max);
b32 gui_select(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const char *txt, u32 *val, u32 opt);
b32 gui_mselect(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const char *txt, u32 *val, u32 opt);
b32 gui_dropdown_begin(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
u32 *val, u32 num_items);
b32 gui_dropdown_item(gui_t *gui, u32 id, const char *txt);
void gui_dropdown_end(gui_t *gui);
typedef void(*gui_drag_f)(s32 *x, s32 *y, s32 mouse_x, s32 mouse_y,
s32 offset_x, s32 offset_y, void *udata);
void gui_drag_func_default(s32 *x, s32 *y, s32 mouse_x, s32 mouse_y,
s32 offset_x, s32 offset_y, void *udata);
void gui_drag_func_horizontal(s32 *x, s32 *y, s32 mouse_x, s32 mouse_y,
s32 offset_x, s32 offset_y, void *udata);
void gui_drag_func_vertical(s32 *x, s32 *y, s32 mouse_x, s32 mouse_y,
s32 offset_x, s32 offset_y, void *udata);
b32 gui_drag(gui_t *gui, s32 *x, s32 *y, b32 contains_mouse, gui_mouse_button_e mb);
b32 gui_dragf(gui_t *gui, s32 *x, s32 *y, b32 contains_mouse, gui_mouse_button_e mb,
gui_drag_f cb, void *udata);
b32 gui_drag_rect(gui_t *gui, s32 *x, s32 *y, s32 w, s32 h, gui_mouse_button_e mb);
b32 gui_drag_rectf(gui_t *gui, s32 *x, s32 *y, s32 w, s32 h, gui_mouse_button_e mb,
gui_drag_f cb, void *udata);
b32 gui_drag_circ(gui_t *gui, s32 *x, s32 *y, s32 r, gui_mouse_button_e mb);
b32 gui_drag_circf(gui_t *gui, s32 *x, s32 *y, s32 r, gui_mouse_button_e mb,
gui_drag_f cb, void *udata);
b32 gui_menu_begin(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const char *txt, s32 item_w, u32 num_items);
void gui_menu_end(gui_t *gui);
b32 gui_color_picker_sv(gui_t *gui, s32 x, s32 y, s32 w, s32 h, colorf_t *c);
b32 gui_color_picker_h(gui_t *gui, s32 x, s32 y, s32 w, s32 h, colorf_t *c);
b32 gui_color_picker_begin(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
s32 pw, s32 ph, colorf_t c);
b32 gui_color_picker_popup_default(gui_t *gui, colorf_t *c);
void gui_color_picker_end(gui_t *gui);
b32 gui_color_picker8_begin(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
s32 pw, s32 ph, color_t c);
b32 gui_color_picker8_popup_default(gui_t *gui, color_t *c);
void gui_color_picker8_update_color(gui_t *gui, color_t *c);
void gui_color_picker8_end(gui_t *gui);
b32 gui_color_picker(gui_t *gui, s32 s, s32 y, s32 w, s32 h,
s32 pw, s32 ph, colorf_t *c);
b32 gui_color_picker8(gui_t *gui, s32 s, s32 y, s32 w, s32 h,
s32 pw, s32 ph, color_t *c);
void gui_scroll_area_begin(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
gui_scroll_area_t *scroll_area);
void gui_scroll_area_end(gui_t *gui, gui_scroll_area_t *scroll_area);
u64 gui_widget_id(const gui_t *gui, s32 x, s32 y);
void gui_widget_push_base_id(gui_t *gui, u32 id, u32 *prev);
void gui_widget_pop_base_id(gui_t *gui, u32 id, u32 prev);
void gui_widget_change_id(gui_t *gui, u64 src, u64 dst);
void gui_widget_focus_next(gui_t *gui);
void gui_widget_disable_tab_focus(gui_t *gui);
void gui_widget_enable_tab_focus(gui_t *gui);
b32 gui_widget_tab_focus_enabled(const gui_t *gui);
void gui_widget_deactivate(gui_t *gui, u64 id);
b32 gui_widget_hot(const gui_t *gui, u64 id);
b32 gui_widget_active(const gui_t *gui, u64 id);
b32 gui_widget_focused(const gui_t *gui, u64 id);
void gui_widget_animate(gui_t *gui, u64 id);
b32 gui_widget_animated(const gui_t *gui, u64 id, u32 *time);
b32 gui_any_widget_hot(const gui_t *gui);
b32 gui_any_widget_active(const gui_t *gui);
b32 gui_any_widget_has_focus(const gui_t *gui);
b32 gui_any_widget_had_focus(const gui_t *gui);
b32 gui_locked(const gui_t *gui);
u32 gui_lock_count(const gui_t *gui);
void gui_lock(gui_t *gui);
void gui_unlock(gui_t *gui);
/* NOTE: I usually hate 'conditional' methods, but this cleans up usage code */
void gui_lock_if(gui_t *gui, b32 cond, u32 *lock);
void gui_unlock_if(gui_t *gui, u32 lock);
/* Scales splits, panels, and panel grids. A value of 100 means unscaled.
* Be careful calling this between frame_begin & frame_end. */
s32 gui_get_scale(gui_t *gui);
void gui_set_scale(gui_t *gui, s32 scale);
s32 gui_scale_val(const gui_t *gui, s32 val);
s32 gui_scale_val_inverse(const gui_t *gui, s32 val);
/* Grid layout */
/* equally distribute remaining space */
#define GUI_GRID_FLEX 0
/* consume percentage (usually out of 100 - see below) of remaining space */
#define GUI_GRID_PCNT(x) (-x)
#ifndef GUI_GRID_MAX_DEPTH
#define GUI_GRID_MAX_DEPTH 8
#endif
#ifndef GUI_GRID_MAX_CELLS
#define GUI_GRID_MAX_CELLS 128
#endif
typedef enum gui_grid_flex
{
GUI_GRID_FLEX_NONE = 0x0,
GUI_GRID_FLEX_HORIZONTAL = 0x1,
GUI_GRID_FLEX_VERTICAL = 0x2,
GUI_GRID_FLEX_FULL = 0x3,
} gui_grid_flex_e;
typedef struct gui_grid_strip
{
b32 vertical;
s32 *current_cell;
s32 *max_cell;
u32 num_cells;
v2i dim;
} gui_grid_strip_t;
typedef struct gui_grid
{
s32 cells[GUI_GRID_MAX_CELLS];
gui_grid_strip_t strips[GUI_GRID_MAX_DEPTH];
u32 depth;
v2i pos; /* top left */
v2i dim;
v2i start; /* top left */
v2i content_dim;
gui_widget_bounds_t widget_bounds;
struct gui_grid *prev;
} gui_grid_t;
void pgui_grid_begin(gui_t *gui, gui_grid_t *grid, s32 x, s32 y, s32 w, s32 h);
void pgui_grid_end(gui_t *gui, gui_grid_t *grid);
u32 pgui_grid_depth(const gui_t *gui);
void pgui_grid_dimensions(const gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
void pgui_grid_content_dimensions(const gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
/* Cell values are evaluated roughly as follows:
* 1. Subtract pixel values from the total row/column dimension.
* 2. Evaluate GUI_GRID_PCNT values on the remaining dimension.
* 3. Split the remaining dimension evenly amongst GUI_GRID_FLEX cells.
*
* Most of the time, it is not advisable to mix GUI_GRID_PCNT and GUI_GRID_FLEX values,
* and GUI_GRID_PCNT values should total 100 when used. However, the following rules
* apply in the cases where these aren't observed:
*
* If the GUI_GRID_PCNT's total 100, any GUI_GRID_FLEX cells will have 0 dimension.
*
* If the GUI_GRID_PCNT's exceed 100, then they will be used as relative weights
* instead of actual percentages, and any GUI_GRID_FLEX cells will have 0 dimension.
*
* If the GUI_GRID_PCNT's are less than 100 and any GUI_GRID_FLEX cells are present,
* then GUI_GRID_PCNT's will be used as percentages, and the remaining percentage
* will be distributed evenly amongst GUI_GRID_FLEX cells.
*
* If the GUI_GRID_PCNT's are less than 100 and no GUI_GRID_FLEX cells are present,
* then the GUI_GRID_PCNT's will be used as relative weights instead of percentages. */
void pgui_row(gui_t *gui, s32 height, u32 num_cells);
void pgui_row_cells(gui_t *gui, s32 height, const s32 *cells, u32 num_cells);
#define pgui_row_cellsv(gui, height, cells) \
pgui_row_cells(gui, height, cells, countof(cells))
void pgui_row_empty(gui_t *gui, s32 height);
void pgui_row_centered(gui_t *gui, s32 height, s32 width);
void pgui_col(gui_t *gui, s32 width, u32 num_cells);
void pgui_col_cells(gui_t *gui, s32 width, const s32 *cells, u32 num_cells);
#define pgui_col_cellsv(gui, width, cells) \
pgui_col_cells(gui, width, cells, countof(cells))
void pgui_col_empty(gui_t *gui, s32 width);
void pgui_col_centered(gui_t *gui, s32 width, s32 height);
void pgui_cell(const gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
void pgui_cell_consume(gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
void pgui_cell_merge_next(gui_t *gui);
u64 pgui_next_widget_id(const gui_t *gui);
void pgui_strip(const gui_t *gui, s32 *x, s32 *y, s32 *w, s32 *h);
void pgui_spacer(gui_t *gui);
void pgui_spacer_blank(gui_t *gui);
void pgui_txt(gui_t *gui, const char *str);
void pgui_txt_info(gui_t *gui, const char *str);
void pgui_img(gui_t *gui, const gui_img_t *img, gui_img_scale_e scale);
void pgui_pen(gui_t *gui, gui_pen_t pen, const gui_element_style_t *style);
s32 pgui_btn_txt(gui_t *gui, const char *lbl);
s32 pgui_btn_img(gui_t *gui, const gui_img_t *img, gui_img_scale_e scale);
s32 pgui_btn_pen(gui_t *gui, gui_pen_t pen);
s32 pgui_btn_color(gui_t *gui, color_t color);
b32 pgui_chk(gui_t *gui, const char *lbl, b32 *val);
b32 pgui_chk_pen(gui_t *gui, gui_pen_t pen, b32 *val);
s32 pgui_npt_txt(gui_t *gui, char *lbl, u32 n, const char *hint,
gui_npt_flags_e flags);
s32 pgui_npt_txt_ex(gui_t *gui, char *lbl, u32 n, const char *hint,
gui_npt_flags_e flags, gui_npt_filter_p filter);
s32 pgui_npt_val(gui_t *gui, const char *txt, u32 n,
gui_npt_flags_e flags, gui_npt_filter_p filter);
b32 pgui_select(gui_t *gui, const char *lbl, u32 *val, u32 opt);
b32 pgui_mselect(gui_t *gui, const char *txt, u32 *val, u32 opt);
b32 pgui_dropdown_begin(gui_t *gui, u32 *val, u32 num_items);
b32 pgui_dropdown_item(gui_t *gui, u32 id, const char *txt);
void pgui_dropdown_end(gui_t *gui);
b32 pgui_slider_x(gui_t *gui, r32 *val);
b32 pgui_slider_y(gui_t *gui, r32 *val);
b32 pgui_range_x(gui_t *gui, r32 *val, r32 min, r32 max);
b32 pgui_range_y(gui_t *gui, r32 *val, r32 min, r32 max);
b32 pgui_menu_begin(gui_t *gui, const char *txt, s32 item_w, u32 num_items);
void pgui_menu_end(gui_t *gui);
b32 pgui_color_picker_sv(gui_t *gui, colorf_t *color);
b32 pgui_color_picker_h(gui_t *gui, colorf_t *color);
b32 pgui_color_picker(gui_t *gui, s32 pw, s32 ph, colorf_t *c);
b32 pgui_color_picker8(gui_t *gui, s32 pw, s32 ph, color_t *c);
void pgui_scroll_area_begin(gui_t *gui, gui_scroll_area_t *scroll_area);
void pgui_scroll_area_end(gui_t *gui, gui_scroll_area_t *scroll_area);
b32 gui_has_drop_file(const gui_t *gui);
const char *gui_drop_file_buf(const gui_t *gui);
typedef struct gui_tree_node
{
u8 depth;
b8 expanded;
} gui_tree_node_t;
void pgui_tree_begin(gui_t *gui, gui_tree_node_t *nodes, u32 max_nodes,
s32 row_height, s32 indent);
void pgui_tree_end(gui_t *gui);
b32 pgui_tree_node_begin(gui_t *gui);
void pgui_tree_node_end(gui_t *gui);
void pgui_tree_leaf(gui_t *gui);
void gui_pen_tree_collapse(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_tree_restore(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
/* Splits */
#ifndef GUI_SPLIT_RESIZE_BORDER
#define GUI_SPLIT_RESIZE_BORDER 4
#endif
#ifndef GUI_SPLIT_ALIGN_LAST_TO_END
#define GUI_SPLIT_ALIGN_LAST_TO_END 1
#endif
typedef enum gui_split_flags
{
GUI_SPLIT_RESIZABLE = 0x1,
GUI_SPLIT_TEMPORARY = 0x2,
GUI_SPLIT_DIVISIBLE = 0x4,
GUI_SPLIT_FULL = 0x7,
} gui_split_flags_e;
typedef struct gui_split
{
b32 in_use;
s32 flags;
struct gui_split *parent; /* un-owned, only NULL for root */
struct {
struct gui_split *prev; /* un-owned, can be NULL */
struct gui_split *next; /* un-owned, can be NULL */
} siblings;
struct {
b32 vertical;
struct gui_split *first; /* un-owned, can be NULL */
struct gui_split *last; /* un-owned, can be NULL */
} children;
r32 size;
box2i box;
struct gui_panel *panel; /* un-owned, can be NULL */
} gui_split_t;
void gui_set_splits(gui_t *gui, gui_split_t splits[], u32 num_splits);
b32 gui_create_root_split(gui_t *gui, gui_split_t **root);
b32 gui_split2h(gui_t *gui, gui_split_t *parent, gui_split_t **left, r32 size,
gui_split_t **right, gui_split_flags_e flags);
b32 gui_split2v(gui_t *gui, gui_split_t *parent, gui_split_t **top, r32 size,
gui_split_t **bottom, gui_split_flags_e flags);
b32 gui_splitNh(gui_t *gui, gui_split_t *parent, gui_split_t **child,
r32 size, gui_split_flags_e flags);
b32 gui_splitNv(gui_t *gui, gui_split_t *parent, gui_split_t **child,
r32 size, gui_split_flags_e flags);
void gui_splits_compute(gui_t *gui);
void gui_splits_render(gui_t *gui);
/* Panels */
#ifndef GUI_SCROLL_RATE
#define GUI_SCROLL_RATE 20
#endif
#ifndef GUI_PANEL_RESIZE_BORDER
#define GUI_PANEL_RESIZE_BORDER 4
#endif
#ifndef GUI_PANEL_TITLEBAR_HEIGHT
#define GUI_PANEL_TITLEBAR_HEIGHT 20
#endif
#ifndef GUI_PANEL_MAX_TAB_WIDTH
#define GUI_PANEL_MAX_TAB_WIDTH 100
#endif
#ifndef GUI_PANEL_MIN_DIM
#define GUI_PANEL_MIN_DIM 80
#endif
typedef enum gui_panel_flags
{
GUI_PANEL_TITLEBAR = 0x01,
GUI_PANEL_DRAGGABLE = 0x02,
GUI_PANEL_RESIZABLE = 0x04,
GUI_PANEL_CLOSABLE = 0x08,
GUI_PANEL_COLLAPSABLE = 0x10,
GUI_PANEL_SCROLLABLE = 0x20,
GUI_PANEL_DOCKABLE = 0x40,
GUI_PANEL_FULL = 0x7f,
} gui_panel_flags_e;
typedef struct gui_panel
{
struct { s32 x, y, w, h; } unscaled;
struct { s32 x, y, w, h; };
const char *title; /* un-owned, can be NULL */
s32 flags;
u32 id;
intptr userdata;
gui_scroll_area_t scroll_area;
s32 pri;
u32 prev_widget_base_id;
struct gui_panel *prev, *next; /* un-owned, can be NULL */
gui_split_t *split; /* un-owned, can be NULL */
b32 closed;
b32 collapsed;
b32 tabbed_out;
s32 scale_anchor;
} gui_panel_t;
void pgui_panel_init(gui_t *gui, gui_panel_t *panel, u32 id,
s32 x, s32 y, s32 w, s32 h,
const char *title, gui_panel_flags_e flags);
void pgui_panel_init_centered(gui_t *gui, gui_panel_t *panel, u32 id,
s32 w, s32 h,
const char *title, gui_panel_flags_e flags);
void pgui_panel_init_in_split(gui_t *gui, gui_panel_t *panel, u32 id,
gui_split_t *split,
const char *title, gui_panel_flags_e flags);
void pgui_panel_set_size(gui_t *gui, gui_panel_t *panel,
s32 x, s32 y, s32 w, s32 h);
void pgui_panel_add_tab(gui_panel_t *panel, gui_panel_t *tab);
void pgui_panel_remove_tab(gui_t *gui, gui_panel_t *panel);
void pgui_panel_select_tab(gui_panel_t *panel);
b32 pgui_panel(gui_t *gui, gui_panel_t *panel);
void pgui_panel_collapse(gui_panel_t *panel);
void pgui_panel_restore(gui_panel_t *panel);
void pgui_panel_open(gui_t *gui, gui_panel_t *panel);
void pgui_panel_open_if_closed(gui_t *gui, gui_panel_t *panel);
void pgui_panel_close(gui_t *gui, gui_panel_t *panel);
void pgui_panel_toggle(gui_t *gui, gui_panel_t *panel);
void pgui_panel_finish(gui_t *gui, gui_panel_t *panel);
b32 pgui_panel_content_visible(const gui_panel_t *panel);
s32 pgui_panel_body_height(const gui_t *gui, const gui_panel_t *panel);
void pgui_panel_to_front(gui_t *gui, gui_panel_t *panel);
int pgui_panel_sort(const void *lhs, const void *rhs);
int pgui_panel_sortp(const void *lhs, const void *rhs);
void pgui_panel_grid_begin(gui_t *gui, gui_grid_flex_e flex);
void pgui_panel_grid_end(gui_t *gui);
/* can return NULL if no panel is currently active */
gui_panel_t *pgui_current_panel(gui_t *gui);
const gui_panel_t *pgui_current_panel_c(const gui_t *gui);
void gui_pen_window_minimize(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_window_maximize(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_window_close(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_panel_drag(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_panel_collapse(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_panel_restore(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void gui_pen_panel_close(gui_t *gui, s32 x, s32 y, s32 w, s32 h,
const gui_element_style_t *style);
void pgui_scroll_area_grid_begin(gui_t *gui, gui_grid_t *grid, gui_grid_flex_e flex);
void pgui_scroll_area_grid_end(gui_t *gui, gui_grid_t *grid);
/* Style */
typedef struct gui_line_style
{
r32 thickness;
r32 dash_len;
color_t color;
} gui_line_style_t;
typedef struct gui_text_style
{
s32 size;
color_t color;
s32 align;
s32 padding;
b32 wrap;
r32 rotation;
} gui_text_style_t;
typedef struct gui_element_style
{
gui_line_style_t line;
gui_text_style_t text;
color_t bg_color;
color_t outline_color;
} gui_element_style_t;
typedef struct gui_widget_style
{
gui_pen_t pen;
gui_element_style_t inactive;
gui_element_style_t hot;
gui_element_style_t active;
gui_element_style_t disabled; /* only colors are used */
const char *hint;
} gui_widget_style_t;
typedef struct gui_slider_style
{
gui_widget_style_t handle;
gui_widget_style_t track;
b32 track_narrow;
} gui_slider_style_t;
typedef struct gui_padding_style
{
s32 top;
s32 right;
s32 bottom;
s32 left;
} gui_padding_style_t;
typedef struct gui_scroll_area_style
{
color_t bg_color;
gui_padding_style_t padding;
s32 scrollbar_track_width;
gui_slider_style_t scrollbar;
} gui_scroll_area_style_t;
typedef struct gui_shadow_style
{
color_t color;
s32 width;
} gui_shadow_style_t;
typedef struct gui_dropshadow_style
{
color_t color;
s32 offset;
s32 width;
} gui_dropshadow_style_t;
typedef struct gui_dropdown_style
{
gui_widget_style_t btn;
gui_shadow_style_t shadow;
} gui_dropdown_style_t;
typedef struct gui_color_picker_style
{
gui_widget_style_t btn;
gui_shadow_style_t shadow;
} gui_color_picker_style_t;
typedef struct gui_panel_style
{
color_t bg_color;
gui_line_style_t border;
gui_element_style_t titlebar;
gui_widget_style_t drag;
gui_widget_style_t tab;
gui_widget_style_t close;
gui_widget_style_t collapse;
gui_widget_style_t restore;
gui_slider_style_t scrollbar;
color_t cell_bg_color;
color_t cell_border_color;
gui_padding_style_t padding;
gui_dropshadow_style_t shadow;
} gui_panel_style_t;
typedef struct gui_style
{
color_t bg_color;
gui_line_style_t line;
gui_text_style_t txt;
gui_widget_style_t npt;
gui_widget_style_t btn;
gui_widget_style_t chk;
gui_slider_style_t slider;
gui_widget_style_t select;
gui_dropdown_style_t dropdown;
gui_color_picker_style_t color_picker;
gui_widget_style_t drag;
gui_element_style_t hint;
gui_scroll_area_style_t scroll_area;
gui_widget_style_t tree;
gui_panel_style_t panel;
gui_line_style_t split;
gui_widget_style_t txt_info;
char font_path[PATH_MAX];
} gui_style_t;
extern const gui_style_t g_gui_style_default;
extern const gui_style_t g_gui_style_invis;
extern const gui_padding_style_t g_gui_padding_none;
gui_style_t *gui_style(gui_t *gui);
const gui_style_t *gui_style_c(const gui_t *gui);
/* Unlike the rest of the style data, the font path is challenging to hard-code an
* absolute path for. We require it to be passed separately in an attempt to make
* this concern more apparent. You can pass the new style's font path if this doesn't
* affect your use case, and you can pass the current style's font path if you want
* to keep it instead of applying the new style's font path. */
void gui_style_set(gui_t *gui, const gui_style_t *style, const char *path);
#define gui_style_set_widget(gui, widget, loc, val) \
do { \
gui_style(gui)->widget.inactive.loc = (val); \
gui_style(gui)->widget.hot.loc = (val); \
gui_style(gui)->widget.active.loc = (val); \
gui_style(gui)->widget.disabled.loc = (val); \
} while (0)
typedef enum gui_widget_render_state
{
GUI_WIDGET_RENDER_INACTIVE,
GUI_WIDGET_RENDER_HOT,
GUI_WIDGET_RENDER_ACTIVE,
} gui_widget_render_state_e;
gui_element_style_t gui_element_style(const gui_t *gui,
gui_widget_render_state_e render_state,
const gui_widget_style_t *widget_style);
/* Temporarily modifying styles is done through the style stack. To change
* a value in the style struct, you can push and pop values for struct members
* of gui_style_t.
*
* gui_style_push_s32(gui, txt.size, 18);
* gui_txt(gui, "Test");
* gui_style_pop(gui);
*
* Due to implementation details, you must explicity specify the field type
* (like 's32') if the value is a literal. Otherwise, you can call
* gui_style_push() with any type of value.
*
* Often, it is desirable to change a single field for every state of a widget
* so the widget looks similar whether it is inactive, hot, active, or disabled.
*
* gui_style_push_widget_s32(gui, btn, txt.size, 18);
* pgui_btn_txt(gui, "Test");
* gui_style_pop_widget(gui);
*
* Make sure every push has a matching pop. Failure to do so shouldn't crash
* the application, but it will cause weird styling behavior and trigger an
* assertion in debug mode.
*
* Unfortunately, to make the calling code simple, the interface is rather
* macro-heavy. */
/* maximum size (in bytes) of the style stack */
#ifndef GUI_STYLE_STACK_LIMIT
#define GUI_STYLE_STACK_LIMIT 2048
#endif