forked from ocornut/imgui
-
Notifications
You must be signed in to change notification settings - Fork 1
/
imgui.cpp
13463 lines (11857 loc) · 570 KB
/
imgui.cpp
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
// ImGui library v1.44 WIP
// See ImGui::ShowTestWindow() for sample code.
// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Get latest version at https://github.com/ocornut/imgui
// Developed by Omar Cornut and ImGui contributors.
/*
Index
- MISSION STATEMENT
- END-USER GUIDE
- PROGRAMMER GUIDE (read me!)
- API BREAKING CHANGES (read me when you update!)
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
- How do I update to a newer version of ImGui?
- Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
- Why is my text output blurry?
- How can I load a different font than the default?
- How can I load multiple fonts?
- How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
- ISSUES & TODO-LIST
- CODE
- SAMPLE CODE
- DEFAULT FONT DATA
MISSION STATEMENT
=================
- easy to use to create code-driven and data-driven tools
- easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools
- easy to hack and improve
- minimize screen real-estate usage
- minimize setup and maintenance
- minimize state storage on user side
- portable, minimize dependencies, run on target (consoles, phones, etc.)
- efficient runtime (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything)
- read about immediate-mode gui principles @ http://mollyrocket.com/861, http://mollyrocket.com/forums/index.html
Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
- doesn't look fancy, doesn't animate
- limited layout features, intricate layouts are typically crafted in code
- occasionally uses statically sized buffers for string manipulations - won't crash, but some very long pieces of text may be clipped. functions like ImGui::TextUnformatted() don't have such restriction.
END-USER GUIDE
==============
- double-click title bar to collapse window
- click upper right corner to close a window, available when 'bool* p_opened' is passed to ImGui::Begin()
- click and drag on lower right corner to resize window
- click and drag on any empty space to move window
- double-click/double-tap on lower right corner grip to auto-fit to content
- TAB/SHIFT+TAB to cycle through keyboard editable fields
- use mouse wheel to scroll
- use CTRL+mouse wheel to zoom window contents (if IO.FontAllowScaling is true)
- CTRL+Click on a slider or drag box to input value as text
- text editor:
- Hold SHIFT or use mouse to select text.
- CTRL+Left/Right to word jump
- CTRL+Shift+Left/Right to select words
- CTRL+A our Double-Click to select all
- CTRL+X,CTRL+C,CTRL+V to use OS clipboard
- CTRL+Z,CTRL+Y to undo/redo
- ESCAPE to revert text to its original value
- You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
PROGRAMMER GUIDE
================
- read the FAQ below this section!
- your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
- call and read ImGui::ShowTestWindow() for sample code demonstrating most features.
- see examples/ folder for standalone sample applications. e.g. examples/opengl_example/
- customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
- getting started:
- initialisation: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the 'Settings' data.
- every frame:
1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the 'Input' data, then call ImGui::NewFrame().
2/ use any ImGui function you want between NewFrame() and Render()
3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
- all rendering information are stored into command-lists until ImGui::Render() is called.
- ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
- effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
- refer to the examples applications in the examples/ folder for instruction on how to setup your code.
- a typical application skeleton may be:
// Application init
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize.x = 1920.0f;
io.DisplaySize.y = 1280.0f;
io.DeltaTime = 1.0f/60.0f;
io.IniFilename = "imgui.ini";
// TODO: Fill others settings of the io structure
// Load texture
unsigned char* pixels;
int width, height, bytes_per_pixels;
io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height, &bytes_per_pixels);
// TODO: copy texture to graphics memory.
// TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
// Application main loop
while (true)
{
// 1) get low-level input
// e.g. on Win32, GetKeyboardState(), or poll your events, etc.
// 2) TODO: fill all fields of IO structure and call NewFrame
ImGuiIO& io = ImGui::GetIO();
io.MousePos = mouse_pos;
io.MouseDown[0] = mouse_button_0;
io.KeysDown[i] = ...
ImGui::NewFrame();
// 3) most of your application code here - you can use any of ImGui::* functions at any point in the frame
ImGui::Begin("My window");
ImGui::Text("Hello, world.");
ImGui::End();
GameUpdate();
GameRender();
// 4) render & swap video buffers
ImGui::Render();
// swap video buffer, etc.
}
- after calling ImGui::NewFrame() you can read back 'io.WantCaptureMouse' and 'io.WantCaptureKeyboard' to tell if ImGui
wants to use your inputs. if it does you can discard/hide the inputs from the rest of your application.
API BREAKING CHANGES
====================
Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
- 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
- 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
- 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
- if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
- the signature of the io.RenderDrawListsFn handler has changed!
ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
became:
ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
argument 'cmd_lists' -> 'draw_data->CmdLists'
argument 'cmd_lists_count' -> 'draw_data->CmdListsCount'
ImDrawList 'commands' -> 'CmdBuffer'
ImDrawList 'vtx_buffer' -> 'VtxBuffer'
ImDrawList n/a -> 'IdxBuffer' (new)
ImDrawCmd 'vtx_count' -> 'ElemCount'
ImDrawCmd 'clip_rect' -> 'ClipRect'
ImDrawCmd 'user_callback' -> 'UserCallback'
ImDrawCmd 'texture_id' -> 'TextureId'
- each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
- if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
- refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
- 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
- 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
- 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
- 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
- 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!
- 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
- 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
- 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
- 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "opened" state of a popup. BeginPopup() returns true if the popup is opened.
- 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
- 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function (will obsolete).
- 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
- 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
- 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
- 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function (will obsolete).
- 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
- 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function (will obsolete).
- 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth
- 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function (will obsolete).
- 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
- 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
- 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
- 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
- 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
- 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
- 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
(1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
this sequence:
const void* png_data;
unsigned int png_size;
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
// <Copy to GPU>
became:
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// <Copy to GPU>
io.Fonts->TexID = (your_texture_identifier);
you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
it is now recommended your sample the font texture with bilinear interpolation.
(1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
(1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
(1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
- 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
- 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
- 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
- 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
- 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)
- 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
- 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
- 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
- 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
- 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
- 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
======================================
Q: How do I update to a newer version of ImGui?
A: Overwrite the following files:
imgui.cpp
imgui.h
stb_rect_pack.h
stb_textedit.h
stb_truetype.h
Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name
in the code, there will likely be a comment about it. Please report any issue to the GitHub page!
Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
A: Yes. A primer on the use of labels/IDs in ImGui..
- Elements that are not clickable, such as Text() items don't need an ID.
- Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget).
to do so they need an unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
Button("OK"); // Label = "OK", ID = hash of "OK"
Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
- ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows
or in two different locations of a tree.
- if you have a same ID twice in the same location, you'll have a conflict:
Button("OK");
Button("OK"); // ID collision! Both buttons will be treated as the same.
Fear not! this is easy to solve and there are many ways to solve it!
- when passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.
use "##" to pass a complement to the ID that won't be visible to the end-user:
Button("Play##0"); // Label = "Play", ID = hash of "Play##0"
Button("Play##1"); // Label = "Play", ID = hash of "Play##1" (different from above)
- so if you want to hide the label but need an ID:
Checkbox("##On", &b); // Label = "", ID = hash of "##On"
- occasionally (rarely) you might want change a label while preserving a constant ID. This allows you to animate labels.
use "###" to pass a label that isn't part of ID:
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
- use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
this is the most convenient way of distinguish ID if you are iterating and creating many UI elements.
you can push a pointer, a string or an integer value. remember that ID are formed from the addition of everything in the ID stack!
for (int i = 0; i < 100; i++)
{
PushID(i);
Button("Click"); // Label = "Click", ID = hash of integer + "label" (unique)
PopID();
}
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj);
Button("Click"); // Label = "Click", ID = hash of pointer + "label" (unique)
PopID();
}
for (int i = 0; i < 100; i++)
{
MyObject* obj = Objects[i];
PushID(obj->Name);
Button("Click"); // Label = "Click", ID = hash of string + "label" (unique)
PopID();
}
- more example showing that you can stack multiple prefixes into the ID stack:
Button("Click"); // Label = "Click", ID = hash of "Click"
PushID("node");
Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
PushID(my_ptr);
Button("Click"); // Label = "Click", ID = hash of "node" + ptr + "Click"
PopID();
PopID();
- tree nodes implicitly creates a scope for you by calling PushID().
Button("Click"); // Label = "Click", ID = hash of "Click"
if (TreeNode("node"))
{
Button("Click"); // Label = "Click", ID = hash of "node" + "Click"
TreePop();
}
- when working with trees, ID are used to preserve the opened/closed state of each tree node.
depending on your use cases you may want to use strings, indices or pointers as ID.
e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change.
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense!
Q: Why is my text output blurry?
A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
A: Use the font atlas to load the TTF file you want:
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
Q: How can I load multiple fonts?
A: Use the font atlas to pack them into a single texture:
ImFont* font0 = io.Fonts->AddFontDefault();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
// the first loaded font gets used by default
// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
// Options
ImFontConfig config;
config.OversampleH = 3;
config.OversampleV = 3;
config.GlyphExtraSpacing.x = 1.0f;
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config);
// Merging input from different fonts into one
ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontDefault();
io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges);
io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese());
Q: How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. ImGui will support UTF-8 encoding across the board.
Character input depends on you passing the right character code to io.AddInputCharacter(). The example applications do that.
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese characters
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
io.ImeWindowHandle = MY_HWND; // To input using Microsoft IME, give ImGui the hwnd of your application
- tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code.
- tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug"
- tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
- tip: you can call Render() multiple times (e.g for VR renders).
- tip: call and read the ShowTestWindow() code for more example of how to use ImGui!
ISSUES & TODO-LIST
==================
Issue numbers (#) refer to github issues.
- misc: merge or clarify ImVec4 vs ImRect?
- window: autofit feedback loop when user relies on any dynamic layout (window width multiplier, column). maybe just clearly drop manual autofit?
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list.
- window: allow resizing of child windows (possibly given min/max for each axis?)
- window: background options for child windows, border option (disable rounding)
- window: resizing from any sides? + mouse cursor directives for app.
- window: get size/pos helpers given names (see discussion in #249)
- scrolling: add horizontal scroll
!- scrolling: allow immediately effective change of scroll if we haven't appended items yet
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc.
- widgets: clean up widgets internal toward exposing everything.
- main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them.
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200)
- input text multi-line: line numbers? status bar? (follow up on #200)
!- input number: large int not reliably supported because of int<>float conversions.
- input number: optional range min/max for Input*() functions
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
- input number: use mouse wheel to step up/down
- input number: non-decimal input.
- text: proper alignment options
- layout: horizontal layout helper (#97)
- layout: more generic alignment state (left/right/centered) for single items?
- layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
- columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125)
- columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
- columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
- columns: user specify columns size (#125)
- popup: border options. richer api like BeginChild() perhaps? (#197)
- combo: sparse combo boxes (via function call?)
- combo: turn child handling code into pop up helper
- combo: contents should extends to fit label if combo widget is small
- combo/listbox: keyboard control. need inputtext like non-active focus + key handling. considering keybord for custom listbox (pr #203)
- listbox: multiple selection
- listbox: user may want to initial scroll to focus on the one selected value?
- listbox: keyboard navigation.
- listbox: scrolling should track modified selection.
- menus: local shortcuts, global shortcuts (#126)
- menus: icons
- menus: menubars: some sort of priority / effect of main menu-bar on desktop size?
- tabs
- separator: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y)
- gauge: various forms of gauge/loading bars widgets
- color: better color editor.
- plot: plotlines should use the polygon-stroke facilities (currently issues with averaging normals)
- plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
- plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
- file selection widget -> build the tool in our codebase to improve model-dialog idioms
- inputfloat: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
- slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
- slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar).
- slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
- dragfloat: up/down axis
- text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
- text edit: centered text for slider as input text so it matches typical positioning.
- text edit: flag to disable live update of the user buffer.
- text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text?
- tree: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
- settings: write more decent code to allow saving/loading new fields
- settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
- style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
- style: checkbox: padding for "active" color should be a multiplier of the
- style: colorbox not always square?
- text: simple markup language for color change?
- log: LogButtons() options for specifying depth and/or hiding depth slider
- log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
- log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
- log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
- filters: set a current filter that tree node can automatically query to hide themselves
- filters: handle wildcards (with implicit leading/trailing *), regexps
- shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus)
!- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing
- keyboard: full keyboard navigation and focus.
- input: rework IO to be able to pass actual events to fix temporal aliasing issues.
- input: support track pad style scrolling & slider edit.
- portability: big-endian test/support (#81)
- drawlist: add support for anti-aliased lines with >1.0f thickness (#133)
- memory: add a way to discard allocs of unused/transient windows. with the current architecture new windows (including popup, opened combos, listbox) perform at least 3 allocs.
- misc: mark printf compiler attributes on relevant functions
- misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
- misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
- style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space?
- style editor: color child window height expressed in multiple of line height.
- optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
- optimization: turn some the various stack vectors into statically-sized arrays
- optimization: better clipping for multi-component widgets
*/
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#include <ctype.h> // toupper, isprint
#include <math.h> // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf
#include <stdio.h> // vsnprintf, sscanf, printf
#include <new> // new (ptr)
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h> // alloca
#else
#include <alloca.h> // alloca
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t
#else
#include <stdint.h> // intptr_t
#endif
#ifdef _MSC_VER
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#define snprintf _snprintf
#endif
// Clang warnings with -Weverything
#ifdef __clang__
#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning : function xx could be declared with attribute 'noreturn' warning // GetDefaultFontData() asserts which some implementation makes it never return.
#pragma clang diagnostic ignored "-Wdeprecated-declarations"// warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
#endif
//-------------------------------------------------------------------------
// STB libraries implementation
//-------------------------------------------------------------------------
struct ImGuiTextEditState;
//#define IMGUI_STB_NAMESPACE ImStb
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
#ifdef IMGUI_STB_NAMESPACE
namespace IMGUI_STB_NAMESPACE
{
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#endif
#define STBRP_ASSERT(x) IM_ASSERT(x)
#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
#define STBRP_STATIC
#define STB_RECT_PACK_IMPLEMENTATION
#endif
#include "stb_rect_pack.h"
#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x))
#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x))
#define STBTT_assert(x) IM_ASSERT(x)
#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION
#else
#define STBTT_DEF extern
#endif
#include "stb_truetype.h"
#undef STB_TEXTEDIT_STRING
#undef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_STRING ImGuiTextEditState
#define STB_TEXTEDIT_CHARTYPE ImWchar
#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
#include "stb_textedit.h"
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef IMGUI_STB_NAMESPACE
} // namespace ImStb
using namespace IMGUI_STB_NAMESPACE;
#endif
//-------------------------------------------------------------------------
// Forward Declarations
//-------------------------------------------------------------------------
struct ImRect;
struct ImGuiColMod;
struct ImGuiStyleMod;
struct ImGuiDrawContext;
struct ImGuiTextEditState;
struct ImGuiIniData;
struct ImGuiState;
struct ImGuiWindow;
typedef int ImGuiLayoutType; // enum ImGuiLayoutType_
typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_
static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags = 0);
static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
static void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align = ImGuiAlign_Default, const ImVec2* clip_min = NULL, const ImVec2* clip_max = NULL);
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false);
static void RenderCheckMark(ImVec2 pos, ImU32 col);
static void SetFont(ImFont* font);
static bool ItemAdd(const ImRect& bb, const ImGuiID* id);
static void ItemSize(ImVec2 size, float text_offset_y = 0.0f);
static void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
static void PushColumnClipRect(int column_index = -1);
static bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged);
static bool IsMouseHoveringRect(const ImRect& bb);
static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
static void Scrollbar(ImGuiWindow* window);
static bool CloseWindowButton(bool* p_opened = NULL);
static void FocusWindow(ImGuiWindow* window);
static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
static void CloseInactivePopups();
static ImGuiWindow* GetFrontMostModalRootWindow();
static void SetWindowScrollY(ImGuiWindow* window, float scroll_y);
// Helpers: String
static int ImStricmp(const char* str1, const char* str2);
static int ImStrnicmp(const char* str1, const char* str2, int count);
static char* ImStrdup(const char* str);
static int ImStrlenW(const ImWchar* str);
static const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end);
static int ImFormatString(char* buf, int buf_size, const char* fmt, ...);
static int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args);
// Helpers: Misc
static ImU32 ImHash(const void* data, int data_size, ImU32 seed);
static bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, int* out_file_size, int padding_bytes = 0);
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
// Helpers: UTF-8 <> wchar
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int in_char); // return output UTF-8 bytes count
static int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
static int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
static int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
static inline int ImTextCountUtf8BytesFromChar(unsigned int in_char); // return output UTF-8 bytes count
static int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points
//-----------------------------------------------------------------------------
// Platform dependent default implementations
//-----------------------------------------------------------------------------
static const char* GetClipboardTextFn_DefaultImpl();
static void SetClipboardTextFn_DefaultImpl(const char* text);
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
//-----------------------------------------------------------------------------
// User facing structures
//-----------------------------------------------------------------------------
ImGuiStyle::ImGuiStyle()
{
Alpha = 1.0f; // Global alpha applies to everything in ImGui
WindowPadding = ImVec2(8,8); // Padding within a window
WindowMinSize = ImVec2(32,32); // Minimum window size
WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text
ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows
FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin()
IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
ScrollbarWidth = 16.0f; // Width of the vertical scrollbar
ScrollbarRounding = 0.0f; // Radius of grab corners rounding for scrollbar
GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f);
Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);
Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);
Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f);
Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
Colors[ImGuiCol_TitleBgActive] = ImVec4(0.50f, 0.50f, 1.00f, 0.55f);
Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.60f);
Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f);
Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
Colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f);
Colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f);
Colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
Colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
Colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
Colors[ImGuiCol_Column] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
Colors[ImGuiCol_ColumnHovered] = ImVec4(0.70f, 0.60f, 0.60f, 1.00f);
Colors[ImGuiCol_ColumnActive] = ImVec4(0.90f, 0.70f, 0.70f, 1.00f);
Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}
// Statically allocated font atlas. This is merely a maneuver to keep ImFontAtlas definition at the bottom of the .h file (otherwise it'd be inside ImGuiIO)
// Also we wouldn't be able to new() one at this point, before users may define IO.MemAllocFn.
static ImFontAtlas GDefaultFontAtlas;
ImGuiIO::ImGuiIO()
{
// Most fields are initialized with zero
memset(this, 0, sizeof(*this));
DisplaySize = ImVec2(-1.0f, -1.0f);
DeltaTime = 1.0f/60.0f;
IniSavingRate = 5.0f;
IniFilename = "imgui.ini";
LogFilename = "imgui_log.txt";
Fonts = &GDefaultFontAtlas;
FontGlobalScale = 1.0f;
MousePos = ImVec2(-1,-1);
MousePosPrev = ImVec2(-1,-1);
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
MouseDragThreshold = 6.0f;
for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1;
KeyRepeatDelay = 0.250f;
KeyRepeatRate = 0.050f;
UserData = NULL;
// User functions
RenderDrawListsFn = NULL;
MemAllocFn = malloc;
MemFreeFn = free;
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
}
//-----------------------------------------------------------------------------
// HELPERS
//-----------------------------------------------------------------------------
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
const float IM_PI = 3.14159265358979323846f;
#ifdef INT_MAX
#define IM_INT_MIN INT_MIN
#define IM_INT_MAX INT_MAX
#else
#define IM_INT_MIN (-2147483647-1)
#define IM_INT_MAX (2147483647)
#endif
// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
#ifdef _MSC_VER
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif
// Pass in translated ASCII characters for text input.
// - with glfw you can get those from the callback set in glfwSetCharCallback()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(ImWchar c)
{
const int n = ImStrlenW(InputCharacters);
if (n + 1 < IM_ARRAYSIZE(InputCharacters))
{
InputCharacters[n] = c;
InputCharacters[n+1] = '\0';
}
}
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
{
// We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more
const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar);
ImWchar wchars[wchars_buf_len];
ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL);
for (int i = 0; wchars[i] != 0 && i < wchars_buf_len; i++)
AddInputCharacter(wchars[i]);
}
// Math bits
// We are keeping those static in the .cpp file so as not to leak them outside, in the case the user has implicit cast operators between ImVec2 and its own types.
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
//static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
//static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
//static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-lhs.w); }
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }
static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }
static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); }
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
static bool ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c)
{
bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
static int ImStricmp(const char* str1, const char* str2)
{
int d;
while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
return d;
}
static int ImStrnicmp(const char* str1, const char* str2, int count)
{
int d = 0;
while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
return d;
}
static char* ImStrdup(const char *str)
{
char *buff = (char*)ImGui::MemAlloc(strlen(str) + 1);
IM_ASSERT(buff);
strcpy(buff, str);
return buff;
}
static int ImStrlenW(const ImWchar* str)
{
int n = 0;
while (*str++) n++;
return n;
}
static const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
{
while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
buf_mid_line--;
return buf_mid_line;
}
static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
{
if (!needle_end)
needle_end = needle + strlen(needle);
const char un0 = (char)toupper(*needle);
while (*haystack)
{
if (toupper(*haystack) == un0)
{
const char* b = needle + 1;
for (const char* a = haystack + 1; b < needle_end; a++, b++)
if (toupper(*a) != toupper(*b))
break;
if (b == needle_end)
return haystack;
}
haystack++;
}
return NULL;
}
// Pass data_size==0 for zero-terminated string
// Try to replace with FNV1a hash?
static ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0)
{
static ImU32 crc32_lut[256] = { 0 };
if (!crc32_lut[1])
{
const ImU32 polynomial = 0xEDB88320;
for (ImU32 i = 0; i < 256; i++)
{
ImU32 crc = i;
for (ImU32 j = 0; j < 8; j++)
crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
crc32_lut[i] = crc;
}
}
seed = ~seed;
ImU32 crc = seed;
const unsigned char* current = (const unsigned char*)data;
if (data_size > 0)
{
// Known size
while (data_size--)
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
}
else
{
// Zero-terminated string
while (unsigned char c = *current++)
{
// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
// Because this syntax is rarely used we are optimizing for the common case.
// - If we reach ### in the string we discard the hash so far and reset to the seed.
// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
if (c == '#' && current[0] == '#' && current[1] == '#')
crc = seed;
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
}
}
return ~crc;
}
static int ImFormatString(char* buf, int buf_size, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
int w = vsnprintf(buf, buf_size, fmt, args);
va_end(args);
buf[buf_size-1] = 0;
return (w == -1) ? buf_size : w;
}
static int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
{
int w = vsnprintf(buf, buf_size, fmt, args);
buf[buf_size-1] = 0;
return (w == -1) ? buf_size : w;
}
ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
{
ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f));
out |= ((ImU32)(ImSaturate(in.y)*255.f) << 8);
out |= ((ImU32)(ImSaturate(in.z)*255.f) << 16);
out |= ((ImU32)(ImSaturate(in.w)*255.f) << 24);
return out;
}
// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
{
float K = 0.f;
if (g < b)
{
const float tmp = g; g = b; b = tmp;
K = -1.f;
}
if (r < g)
{
const float tmp = r; r = g; g = tmp;
K = -2.f / 6.f - K;
}
const float chroma = r - (g < b ? g : b);
out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));
out_s = chroma / (r + 1e-20f);
out_v = r;
}
// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
// also http://en.wikipedia.org/wiki/HSL_and_HSV
void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
{
if (s == 0.0f)
{
// gray
out_r = out_g = out_b = v;
return;
}
h = fmodf(h, 1.0f) / (60.0f/360.0f);
int i = (int)h;
float f = h - (float)i;
float p = v * (1.0f - s);
float q = v * (1.0f - s * f);
float t = v * (1.0f - s * (1.0f - f));
switch (i)