OpenRaider  0.1.4-dev
Open Source Tomb Raider Game Engine implementation
imgui.cpp
Go to the documentation of this file.
1 // ImGui library v1.35
2 // See ImGui::ShowTestWindow() for sample code.
3 // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
4 // Get latest version at https://github.com/ocornut/imgui
5 // Developed by Omar Cornut and contributors.
6 
7 /*
8 
9  Index
10  - MISSION STATEMENT
11  - END-USER GUIDE
12  - PROGRAMMER GUIDE (read me!)
13  - API BREAKING CHANGES (read me when you update!)
14  - FREQUENTLY ASKED QUESTIONS (FAQ) & TROUBLESHOOTING (read me!)
15  - ISSUES & TODO-LIST
16  - CODE
17  - SAMPLE CODE
18  - FONT DATA
19 
20 
21  MISSION STATEMENT
22  =================
23 
24  - easy to use to create code-driven and data-driven tools
25  - easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools
26  - easy to hack and improve
27  - minimize screen real-estate usage
28  - minimize setup and maintenance
29  - minimize state storage on user side
30  - portable, minimize dependencies, run on target (consoles, phones, etc.)
31  - 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)
32  - read about immediate-mode gui principles @ http://mollyrocket.com/861, http://mollyrocket.com/forums/index.html
33 
34  Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
35  - doesn't look fancy, doesn't animate
36  - limited layout features, intricate layouts are typically crafted in code
37  - occasionally uses statically sized buffers for string manipulations - won't crash, but some long text may be clipped. functions like ImGui::TextUnformatted() don't have such restriction.
38 
39 
40  END-USER GUIDE
41  ==============
42 
43  - double-click title bar to collapse window
44  - click upper right corner to close a window, available when 'bool* p_opened' is passed to ImGui::Begin()
45  - click and drag on lower right corner to resize window
46  - click and drag on any empty space to move window
47  - double-click/double-tap on lower right corner grip to auto-fit to content
48  - TAB/SHIFT+TAB to cycle through keyboard editable fields
49  - use mouse wheel to scroll
50  - use CTRL+mouse wheel to zoom window contents (if IO.FontAllowScaling is true)
51  - CTRL+Click on a slider to input value as text
52  - text editor:
53  - Hold SHIFT or use mouse to select text.
54  - CTRL+Left/Right to word jump
55  - CTRL+Shift+Left/Right to select words
56  - CTRL+A our Double-Click to select all
57  - CTRL+X,CTRL+C,CTRL+V to use OS clipboard
58  - CTRL+Z,CTRL+Y to undo/redo
59  - ESCAPE to revert text to its original value
60  - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
61 
62 
63  PROGRAMMER GUIDE
64  ================
65 
66  - read the FAQ below this section!
67  - 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.
68  - call and read ImGui::ShowTestWindow() for sample code demonstrating most features.
69  - see examples/ folder for standalone sample applications.
70  - customization: use the style editor or PushStyleColor/PushStyleVar to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
71 
72  - getting started:
73  - initialisation: call ImGui::GetIO() and fill the 'Settings' data.
74  - every frame:
75  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().
76  2/ use any ImGui function you want between NewFrame() and Render()
77  3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
78  - all rendering information are stored into command-lists until ImGui::Render() is called.
79  - effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
80  - refer to the examples applications in the examples/ folder for instruction on how to setup your code.
81  - a typical application skeleton may be:
82 
83  // Application init
84  ImGuiIO& io = ImGui::GetIO();
85  io.DisplaySize.x = 1920.0f;
86  io.DisplaySize.y = 1280.0f;
87  io.DeltaTime = 1.0f/60.0f;
88  io.IniFilename = "imgui.ini";
89  // TODO: Fill others settings of the io structure
90 
91  // Load texture
92  unsigned char* pixels;
93  int width, height, bytes_per_pixels;
94  io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height, &bytes_per_pixels);
95  // TODO: copy texture to graphics memory.
96  // TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
97 
98  // Application main loop
99  while (true)
100  {
101  // 1) get low-level input
102  // e.g. on Win32, GetKeyboardState(), or poll your events, etc.
103 
104  // 2) TODO: fill all fields of IO structure and call NewFrame
105  ImGuiIO& io = ImGui::GetIO();
106  io.MousePos = mouse_pos;
107  io.MouseDown[0] = mouse_button_0;
108  io.KeysDown[i] = ...
109  ImGui::NewFrame();
110 
111  // 3) most of your application code here - you can use any of ImGui::* functions at any point in the frame
112  ImGui::Begin("My window");
113  ImGui::Text("Hello, world.");
114  ImGui::End();
115  GameUpdate();
116  GameRender();
117 
118  // 4) render & swap video buffers
119  ImGui::Render();
120  // swap video buffer, etc.
121  }
122 
123  - after calling ImGui::NewFrame() you can read back 'io.WantCaptureMouse' and 'io.WantCaptureKeyboard' to tell if ImGui
124  wants to use your inputs. if it does you can discard/hide the inputs from the rest of your application.
125 
126  API BREAKING CHANGES
127  ====================
128 
129  Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
130  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.
131 
132  - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth
133  - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond), kept inline redirection function.
134  - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
135  - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
136  - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
137  - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
138  - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
139  - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
140  - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
141  (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
142  this sequence:
143  const void* png_data;
144  unsigned int png_size;
145  ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
146  // <Copy to GPU>
147  became:
148  unsigned char* pixels;
149  int width, height;
150  io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
151  // <Copy to GPU>
152  io.Fonts->TexID = (your_texture_identifier);
153  you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
154  it is now recommended your sample the font texture with bilinear interpolation.
155  (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
156  (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
157  (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
158  - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
159  - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
160  - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
161  - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
162  - 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)
163  - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
164  - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
165  - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
166  - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
167  - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
168  - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
169 
170 
171  FREQUENTLY ASKED QUESTIONS (FAQ) & TROUBLESHOOTING
172  ==================================================
173 
174  If text or lines are blurry when integrating ImGui in your engine:
175 
176  - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
177 
178  A primer on the meaning and use of ID in ImGui:
179 
180  - widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget).
181  to do so they need an unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
182 
183  Button("OK"); // Label = "OK", ID = hash of "OK"
184  Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
185 
186  - ID are uniquely scoped within Windows so no conflict can happen if you have two buttons called "OK" in two different Windows.
187 
188  - when passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.
189  use "##" to pass a complement to the ID that won't be visible to the end-user:
190 
191  Button("Play##0"); // Label = "Play", ID = hash of "Play##0"
192  Button("Play##1"); // Label = "Play", ID = hash of "Play##1" (different from above)
193 
194  use "###" to pass a label that isn't part of ID. You can use that to change labels while preserving a constant ID.
195 
196  Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
197  Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
198 
199  - use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window:
200 
201  Button("Click"); // Label = "Click", ID = hash of "Click"
202  PushID("node");
203  Button("Click"); // Label = "Click", ID = hash of "node" and "Click"
204  for (int i = 0; i < 100; i++)
205  {
206  PushID(i);
207  Button("Click"); // Label = "Click", ID = hash of "node" and i and "label"
208  PopID();
209  }
210  PopID();
211  PushID(my_ptr);
212  Button("Click"); // Label = "Click", ID = hash of ptr and "Click"
213  PopID();
214 
215  so if you have a loop creating multiple items, you can use PushID() / PopID() with the index of each item, or their pointer, etc.
216  some functions like TreeNode() implicitly creates a scope for you by calling PushID().
217 
218  - when working with trees, ID are used to preserve the opened/closed state of tree nodes.
219  depending on your use cases you may want to use strings, indices or pointers as ID.
220  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.
221  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!
222 
223  If you want to load a different font than the default (ProggyClean.ttf, size 13)
224 
225  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
226  io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
227 
228  If you want to load multiple fonts, use the font atlas to pack them into a single texture!
229 
230  ImFont* font0 = io.Fonts->AddFontDefault();
231  ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
232  ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
233  io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
234 
235  If you want to display Chinese, Japanese, Korean characters, pass custom Unicode ranges when loading a font:
236 
237  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, io.Fonts->GetGlyphRangesJapanese()); // Load Japanese characters
238  io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
239  io.ImeWindowHandle = MY_HWND; // To input using Microsoft IME, give ImGui the hwnd of your application
240 
241  - 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.
242  - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug"
243  - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
244  - tip: you can call Render() multiple times (e.g for VR renders).
245  - tip: call and read the ShowTestWindow() code for more example of how to use ImGui!
246 
247 
248  ISSUES & TODO-LIST
249  ==================
250 
251  - misc: merge or clarify ImVec4 / ImGuiAabb, they are essentially duplicate containers
252  - window: add horizontal scroll
253  - window: fix resize grip rendering scaling along with Rounding style setting
254  - window: autofit feedback loop when user relies on any dynamic layout (window width multiplier, column). maybe just clearly drop manual autofit?
255  - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list.
256  - window: allow resizing of child windows (possibly given min/max for each axis?)
257  - window: background options for child windows, border option (disable rounding)
258  - window: resizing from any sides? + mouse cursor directives for app.
259  - widgets: clicking on widget b while widget a should activate widget b (doesn't anymore because of hover capture)
260  - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc.
261  - widgets: clip text? hover clipped text shows it in a tooltip or in-place overlay
262  - main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them.
263  - main: IsItemHovered() returns true even if mouse is active on another widget (e.g. dragging outside of sliders). Maybe not a sensible default? Add parameter or alternate function?
264  - 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
265  - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
266 !- input number: very large int not reliably supported because of int<>float conversions.
267  - input number: optional range min/max for Input*() functions
268  - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
269  - input number: use mouse wheel to step up/down
270  - input number: non-decimal input.
271  - layout: horizontal layout helper (github issue #97)
272  - layout: more generic alignment state (left/right/centered) for single items?
273  - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
274  - columns: separator function or parameter that works within the column (currently Separator() bypass all columns)
275  - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills)
276  - columns: columns header to act as button (~sort op) and allow resize/reorder
277  - columns: user specify columns size
278  - columns: tree node example, removing the last NextColumn() makes a padding difference (it should not)
279  - combo: turn child handling code into pop up helper
280  - combo: contents should extends to fit label if combo widget is small
281  - listbox: multiple selection
282  - listbox: user may want to initial scroll to focus on the one selected value?
283  ! menubar, menus
284  - tabs
285  - gauge: various forms of gauge/loading bars widgets
286  - color: better color editor.
287  - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
288  - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
289  - 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)
290  - file selection widget -> build the tool in our codebase to improve model-dialog idioms
291  - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
292  - slider: initial absolute click is imprecise. change to relative movement slider? hide mouse cursor, allow more precise input using less screen-space. same as scrollbar.
293  - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
294  - text edit: centered text for slider as input text so it matches typical positioning.
295  - text edit: flag to disable live update of the user buffer.
296  - text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text?
297  - text edit: add multi-line text edit
298  - tree: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
299  - settings: write more decent code to allow saving/loading new fields
300  - settings: api for per-tool simple persistent data (bool,int,float) in .ini file
301  ! style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
302  - style: checkbox: padding for "active" color should be a multiplier of the
303  - style: colorbox not always square?
304  - text: simple markup language for color change?
305  - log: LogButtons() options for specifying depth and/or hiding depth slider
306  - log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
307  - log: be able to right-click and log a window or tree-node into tty/file/clipboard / generalized context menu?
308  - filters: set a current filter that tree node can automatically query to hide themselves
309  - filters: handle wildcards (with implicit leading/trailing *), regexps
310  - 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)
311  ! keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing
312  - keyboard: full keyboard navigation and focus.
313  - input: rework IO to be able to pass actual events to fix temporal aliasing issues.
314  - input: support track pad style scrolling & slider edit.
315  - tooltip: move to fit within screen (e.g. when mouse cursor is right of the screen).
316  - portability: big-endian test/support (github issue #81)
317  - misc: mark printf compiler attributes on relevant functions
318  - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
319  - misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
320  - style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space?
321  - style editor: color child window height expressed in multiple of line height.
322  - optimization/render: use indexed rendering to reduce vertex data cost (for remote/networked imgui)
323  - 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)?
324  - optimization: turn some the various stack vectors into statically-sized arrays
325  - optimization: better clipping for multi-component widgets
326  - optimization: specialize for height based clipping first (assume widgets never go up + height tests before width tests?)
327 */
328 
329 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
330 #define _CRT_SECURE_NO_WARNINGS
331 #endif
332 
333 #include "imgui.h"
334 #include <ctype.h> // toupper
335 #include <math.h> // sqrtf
336 #include <stdint.h> // intptr_t
337 #include <stdio.h> // vsnprintf
338 #include <new> // new (ptr)
339 
340 #ifdef _MSC_VER
341 #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
342 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
343 #endif
344 
345 // Clang warnings with -Weverything
346 #ifdef __clang__
347 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
348 #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
349 #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.
350 #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.
351 #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
352 #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
353 #endif
354 #ifdef __GNUC__
355 #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
356 #endif
357 
358 //-------------------------------------------------------------------------
359 // STB libraries implementation
360 //-------------------------------------------------------------------------
361 
362 struct ImGuiTextEditState;
363 
364 //#define IMGUI_STB_NAMESPACE ImStb
365 //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
366 //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
367 
368 #ifdef IMGUI_STB_NAMESPACE
369 namespace IMGUI_STB_NAMESPACE
370 {
371 #endif
372 
373 #ifdef __clang__
374 #pragma clang diagnostic push
375 #pragma clang diagnostic ignored "-Wunused-function"
376 #pragma clang diagnostic ignored "-Wmissing-prototypes"
377 #endif
378 
379 #define STBRP_ASSERT(x) IM_ASSERT(x)
380 #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
381 #define STBRP_STATIC
382 #define STB_RECT_PACK_IMPLEMENTATION
383 #endif
384 #include "stb_rect_pack.h"
385 
386 #define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x))
387 #define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x))
388 #define STBTT_assert(x) IM_ASSERT(x)
389 #ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
390 #define STBTT_STATIC
391 #define STB_TRUETYPE_IMPLEMENTATION
392 #endif
393 #include "stb_truetype.h"
394 
395 #define STB_TEXTEDIT_STRING ImGuiTextEditState
396 #define STB_TEXTEDIT_CHARTYPE ImWchar
397 #include "stb_textedit.h"
398 
399 #ifdef __clang__
400 #pragma clang diagnostic pop
401 #endif
402 
403 #ifdef IMGUI_STB_NAMESPACE
404 } // namespace ImStb
405 using namespace IMGUI_STB_NAMESPACE;
406 #endif
407 
408 //-------------------------------------------------------------------------
409 // Forward Declarations
410 //-------------------------------------------------------------------------
411 
412 struct ImGuiColMod;
413 struct ImGuiStyleMod;
414 struct ImGuiAabb;
415 struct ImGuiDrawContext;
416 struct ImGuiTextEditState;
417 struct ImGuiIniData;
418 struct ImGuiState;
419 struct ImGuiWindow;
420 
421 static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false);
422 static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
423 
424 static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
425 static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
426 static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max);
427 static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
428 static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale = 1.0f, bool shadow = false);
429 
430 static void SetFont(ImFont* font);
431 static bool ItemAdd(const ImGuiAabb& bb, const ImGuiID* id);
432 static void ItemSize(ImVec2 size, ImVec2* adjust_start_offset = NULL);
433 static void ItemSize(const ImGuiAabb& bb, ImVec2* adjust_start_offset = NULL);
434 static void PushColumnClipRect(int column_index = -1);
435 static bool IsClipped(const ImGuiAabb& bb);
436 
437 static bool IsMouseHoveringBox(const ImGuiAabb& bb);
438 static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
439 
440 static void Scrollbar(ImGuiWindow* window);
441 static bool CloseWindowButton(bool* p_opened = NULL);
442 static void FocusWindow(ImGuiWindow* window);
443 static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
444 
445 // Helpers: String
446 static int ImStricmp(const char* str1, const char* str2);
447 static int ImStrnicmp(const char* str1, const char* str2, int count);
448 static char* ImStrdup(const char *str);
449 static size_t ImStrlenW(const ImWchar* str);
450 static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end);
451 static size_t ImFormatString(char* buf, size_t buf_size, const char* fmt, ...);
452 static size_t ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args);
453 
454 // Helpers: Misc
455 static ImU32 ImHash(const void* data, size_t data_size, ImU32 seed);
456 static bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, size_t* out_file_size, size_t padding_bytes = 0);
457 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; }
458 static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
459 
460 // Helpers: UTF-8 <> wchar
461 static int ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int in_char); // return output UTF-8 bytes count
462 static ptrdiff_t ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
463 static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
464 static ptrdiff_t ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
465 static int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
466 static int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points
467 
468 //-----------------------------------------------------------------------------
469 // Platform dependent default implementations
470 //-----------------------------------------------------------------------------
471 
472 static const char* GetClipboardTextFn_DefaultImpl();
473 static void SetClipboardTextFn_DefaultImpl(const char* text);
474 static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
475 
476 //-----------------------------------------------------------------------------
477 // Texture Atlas data
478 //-----------------------------------------------------------------------------
479 
480 // Technically we should use the rect pack API for that, but it's just simpler to hard-core the positions for now.
481 // As we start using more of the texture atlas (for rounded corners) we can change that.
482 static const ImVec2 TEX_ATLAS_SIZE(32, 32);
483 static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_BLACK(1, 3);
484 static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_WHITE(14, 3);
485 static const ImVec2 TEX_ATLAS_SIZE_MOUSE_CURSOR(12, 19);
486 
487 //-----------------------------------------------------------------------------
488 // User facing structures
489 //-----------------------------------------------------------------------------
490 
492 {
493  Alpha = 1.0f; // Global alpha applies to everything in ImGui
494  WindowPadding = ImVec2(8,8); // Padding within a window
495  WindowMinSize = ImVec2(32,32); // Minimum window size
496  WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
497  ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows
498  FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
499  FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
500  ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
501  ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
502  TouchExtraPadding = ImVec2(0,0); // Expand bounding box for touch-based system where touch position is not accurate enough (unnecessary for mouse inputs). Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget running. So dont grow this too much!
503  AutoFitPadding = ImVec2(8,8); // Extra space after auto-fit (double-clicking on resize grip)
504  WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin()
505  TreeNodeSpacing = 22.0f; // Horizontal spacing when entering a tree node
506  ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
507  ScrollbarWidth = 16.0f; // Width of the vertical scrollbar
508  GrabMinSize = 10.0f; // Minimum width/height of a slider or scrollbar grab
509 
510  Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
511  Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
512  Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
513  Colors[ImGuiCol_Border] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
514  Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
515  Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
516  Colors[ImGuiCol_TitleBg] = ImVec4(0.50f, 0.50f, 1.00f, 0.45f);
517  Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
518  Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.80f, 0.15f);
519  Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
520  Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
521  Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
522  Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
523  Colors[ImGuiCol_CheckHovered] = ImVec4(0.60f, 0.40f, 0.40f, 0.45f);
524  Colors[ImGuiCol_CheckActive] = ImVec4(0.65f, 0.50f, 0.50f, 0.55f);
525  Colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
526  Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
527  Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
528  Colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f);
529  Colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f);
530  Colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
531  Colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
532  Colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
533  Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
534  Colors[ImGuiCol_Column] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
535  Colors[ImGuiCol_ColumnHovered] = ImVec4(0.60f, 0.40f, 0.40f, 1.00f);
536  Colors[ImGuiCol_ColumnActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
537  Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
538  Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
539  Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
540  Colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
541  Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
542  Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
543  Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
544  Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
545  Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
546  Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
547  Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
548  Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
549 }
550 
551 // 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)
552 // Also we wouldn't be able to new() one at this point, before users may define IO.MemAllocFn.
554 
556 {
557  // Most fields are initialized with zero
558  memset(this, 0, sizeof(*this));
559 
560  DisplaySize = ImVec2(-1.0f, -1.0f);
561  DeltaTime = 1.0f/60.0f;
562  IniSavingRate = 5.0f;
563  IniFilename = "imgui.ini";
564  LogFilename = "imgui_log.txt";
565  Fonts = &GDefaultFontAtlas;
566  FontGlobalScale = 1.0f;
567  MousePos = ImVec2(-1,-1);
568  MousePosPrev = ImVec2(-1,-1);
569  MouseDoubleClickTime = 0.30f;
570  MouseDoubleClickMaxDist = 6.0f;
571  UserData = NULL;
572 
573  // User functions
574  RenderDrawListsFn = NULL;
575  MemAllocFn = malloc;
576  MemFreeFn = free;
577  GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
578  SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
579  ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
580 }
581 
582 // Pass in translated ASCII characters for text input.
583 // - with glfw you can get those from the callback set in glfwSetCharCallback()
584 // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
586 {
587  const size_t n = ImStrlenW(InputCharacters);
588  if (n + 1 < sizeof(InputCharacters) / sizeof(InputCharacters[0]))
589  {
590  InputCharacters[n] = c;
591  InputCharacters[n+1] = 0;
592  }
593 }
594 
595 //-----------------------------------------------------------------------------
596 // Helpers
597 //-----------------------------------------------------------------------------
598 
599 #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
600 
601 #undef PI
602 const float PI = 3.14159265358979323846f;
603 
604 #ifdef INT_MAX
605 #define IM_INT_MAX INT_MAX
606 #else
607 #define IM_INT_MAX 2147483647
608 #endif
609 
610 // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
611 #ifdef _MSC_VER
612 #define STR_NEWLINE "\r\n"
613 #else
614 #define STR_NEWLINE "\n"
615 #endif
616 
617 // Math bits
618 // 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.
619 static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
620 //static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
621 static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
622 static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
623 static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2 rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
624 static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2 rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
625 static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
626 static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
627 static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
628 //static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
629 
630 static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
631 static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
632 static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
633 static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
634 static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }
635 static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }
636 static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
637 static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
638 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)); }
639 static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
640 static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
641 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); }
642 static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
643 
644 static int ImStricmp(const char* str1, const char* str2)
645 {
646  int d;
647  while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
648  return d;
649 }
650 
651 static int ImStrnicmp(const char* str1, const char* str2, int count)
652 {
653  int d = 0;
654  while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
655  return d;
656 }
657 
658 static char* ImStrdup(const char *str)
659 {
660  char *buff = (char*)ImGui::MemAlloc(strlen(str) + 1);
661  IM_ASSERT(buff);
662  strcpy(buff, str);
663  return buff;
664 }
665 
666 static size_t ImStrlenW(const ImWchar* str)
667 {
668  size_t n = 0;
669  while (*str++) n++;
670  return n;
671 }
672 
673 static const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
674 {
675  if (!needle_end)
676  needle_end = needle + strlen(needle);
677 
678  const char un0 = (char)toupper(*needle);
679  while (*haystack)
680  {
681  if (toupper(*haystack) == un0)
682  {
683  const char* b = needle + 1;
684  for (const char* a = haystack + 1; b < needle_end; a++, b++)
685  if (toupper(*a) != toupper(*b))
686  break;
687  if (b == needle_end)
688  return haystack;
689  }
690  haystack++;
691  }
692  return NULL;
693 }
694 
695 // Pass data_size==0 for zero-terminated string
696 // Try to replace with FNV1a hash?
697 static ImU32 ImHash(const void* data, size_t data_size, ImU32 seed = 0)
698 {
699  static ImU32 crc32_lut[256] = { 0 };
700  if (!crc32_lut[1])
701  {
702  const ImU32 polynomial = 0xEDB88320;
703  for (ImU32 i = 0; i < 256; i++)
704  {
705  ImU32 crc = i;
706  for (ImU32 j = 0; j < 8; j++)
707  crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
708  crc32_lut[i] = crc;
709  }
710  }
711 
712  seed = ~seed;
713  ImU32 crc = seed;
714  const unsigned char* current = (const unsigned char*)data;
715 
716  if (data_size > 0)
717  {
718  // Known size
719  while (data_size--)
720  crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
721  }
722  else
723  {
724  // Zero-terminated string
725  while (unsigned char c = *current++)
726  {
727  // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
728  // Because this syntax is rarely used we are optimizing for the common case.
729  // - If we reach ### in the string we discard the hash so far and reset to the seed.
730  // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
731  if (c == '#' && current[0] == '#' && current[1] == '#')
732  crc = seed;
733 
734  crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
735  }
736  }
737  return ~crc;
738 }
739 
740 static size_t ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
741 {
742  va_list args;
743  va_start(args, fmt);
744  int w = vsnprintf(buf, buf_size, fmt, args);
745  va_end(args);
746  buf[buf_size-1] = 0;
747  return (w == -1) ? buf_size : (size_t)w;
748 }
749 
750 static size_t ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
751 {
752  int w = vsnprintf(buf, buf_size, fmt, args);
753  buf[buf_size-1] = 0;
754  return (w == -1) ? buf_size : (size_t)w;
755 }
756 
758 {
759  ImU32 out = ((ImU32)(ImSaturate(in.x)*255.f));
760  out |= ((ImU32)(ImSaturate(in.y)*255.f) << 8);
761  out |= ((ImU32)(ImSaturate(in.z)*255.f) << 16);
762  out |= ((ImU32)(ImSaturate(in.w)*255.f) << 24);
763  return out;
764 }
765 
766 // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
767 // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
768 void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
769 {
770  float K = 0.f;
771  if (g < b)
772  {
773  const float tmp = g; g = b; b = tmp;
774  K = -1.f;
775  }
776  if (r < g)
777  {
778  const float tmp = r; r = g; g = tmp;
779  K = -2.f / 6.f - K;
780  }
781 
782  const float chroma = r - (g < b ? g : b);
783  out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));
784  out_s = chroma / (r + 1e-20f);
785  out_v = r;
786 }
787 
788 // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
789 // also http://en.wikipedia.org/wiki/HSL_and_HSV
790 void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
791 {
792  if (s == 0.0f)
793  {
794  // gray
795  out_r = out_g = out_b = v;
796  return;
797  }
798 
799  h = fmodf(h, 1.0f) / (60.0f/360.0f);
800  int i = (int)h;
801  float f = h - (float)i;
802  float p = v * (1.0f - s);
803  float q = v * (1.0f - s * f);
804  float t = v * (1.0f - s * (1.0f - f));
805 
806  switch (i)
807  {
808  case 0: out_r = v; out_g = t; out_b = p; break;
809  case 1: out_r = q; out_g = v; out_b = p; break;
810  case 2: out_r = p; out_g = v; out_b = t; break;
811  case 3: out_r = p; out_g = q; out_b = v; break;
812  case 4: out_r = t; out_g = p; out_b = v; break;
813  case 5: default: out_r = v; out_g = p; out_b = q; break;
814  }
815 }
816 
817 // Load file content into memory
818 // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
819 static bool ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, size_t* out_file_size, size_t padding_bytes)
820 {
821  IM_ASSERT(filename && file_open_mode && out_file_data && out_file_size);
822  IM_ASSERT(padding_bytes >= 0);
823  *out_file_data = NULL;
824  *out_file_size = 0;
825 
826  FILE* f;
827  if ((f = fopen(filename, file_open_mode)) == NULL)
828  return false;
829 
830  long file_size_signed;
831  if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
832  {
833  fclose(f);
834  return false;
835  }
836 
837  size_t file_size = (size_t)file_size_signed;
838  void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
839  if (file_data == NULL)
840  {
841  fclose(f);
842  return false;
843  }
844  if (fread(file_data, 1, file_size, f) != file_size)
845  {
846  fclose(f);
847  ImGui::MemFree(file_data);
848  return false;
849  }
850  if (padding_bytes > 0)
851  memset((void *)(((char*)file_data) + file_size), 0, padding_bytes);
852 
853  fclose(f);
854  *out_file_data = file_data;
855  *out_file_size = file_size;
856 
857  return true;
858 }
859 
860 //-----------------------------------------------------------------------------
861 
862 struct ImGuiColMod // Color modifier, backup of modified data so we can restore it
863 {
864  ImGuiCol Col;
865  ImVec4 PreviousValue;
866 };
867 
868 struct ImGuiStyleMod // Style modifier, backup of modified data so we can restore it
869 {
870  ImGuiStyleVar Var;
871  ImVec2 PreviousValue;
872 };
873 
874 struct ImGuiAabb // 2D axis aligned bounding-box
875 {
876  ImVec2 Min;
877  ImVec2 Max;
878 
879  ImGuiAabb() { Min = ImVec2(FLT_MAX,FLT_MAX); Max = ImVec2(-FLT_MAX,-FLT_MAX); }
880  ImGuiAabb(const ImVec2& min, const ImVec2& max) { Min = min; Max = max; }
881  ImGuiAabb(const ImVec4& v) { Min.x = v.x; Min.y = v.y; Max.x = v.z; Max.y = v.w; }
882  ImGuiAabb(float x1, float y1, float x2, float y2) { Min.x = x1; Min.y = y1; Max.x = x2; Max.y = y2; }
883 
884  ImVec2 GetCenter() const { return Min + (Max-Min)*0.5f; }
885  ImVec2 GetSize() const { return Max-Min; }
886  float GetWidth() const { return (Max-Min).x; }
887  float GetHeight() const { return (Max-Min).y; }
888  ImVec2 GetTL() const { return Min; }
889  ImVec2 GetTR() const { return ImVec2(Max.x,Min.y); }
890  ImVec2 GetBL() const { return ImVec2(Min.x,Max.y); }
891  ImVec2 GetBR() const { return Max; }
892  bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x <= Max.x && p.y <= Max.y; }
893  bool Contains(const ImGuiAabb& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; }
894  bool Overlaps(const ImGuiAabb& r) const { return r.Min.y <= Max.y && r.Max.y >= Min.y && r.Min.x <= Max.x && r.Max.x >= Min.x; }
895  void Add(const ImVec2& rhs) { Min.x = ImMin(Min.x, rhs.x); Min.y = ImMin(Min.y, rhs.y); Max.x = ImMax(Max.x, rhs.x); Max.y = ImMax(Max.x, rhs.x); }
896  void Add(const ImGuiAabb& rhs) { Min.x = ImMin(Min.x, rhs.Min.x); Min.y = ImMin(Min.y, rhs.Min.y); Max.x = ImMax(Max.x, rhs.Max.x); Max.y = ImMax(Max.y, rhs.Max.y); }
897  void Expand(const ImVec2& sz) { Min -= sz; Max += sz; }
898  void Clip(const ImGuiAabb& clip) { Min.x = ImMax(Min.x, clip.Min.x); Min.y = ImMax(Min.y, clip.Min.y); Max.x = ImMin(Max.x, clip.Max.x); Max.y = ImMin(Max.y, clip.Max.y); }
899 };
900 
901 // Temporary per-window data, reset at the beginning of the frame
902 struct ImGuiDrawContext
903 {
904  ImVec2 CursorPos;
905  ImVec2 CursorPosPrevLine;
906  ImVec2 CursorStartPos;
907  float CurrentLineHeight;
908  float PrevLineHeight;
909  float LogLineHeight;
910  int TreeDepth;
911  ImGuiID LastItemID;
912  ImGuiAabb LastItemAabb;
913  bool LastItemHovered;
914  ImVector<ImGuiWindow*> ChildWindows;
915  ImVector<bool> AllowKeyboardFocus;
916  ImVector<float> ItemWidth; // 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
917  ImVector<float> TextWrapPos;
919  ImGuiStorage* StateStorage;
920 
921  float ColumnsStartX; // Start position from left of window (increased by TreePush/TreePop, etc.)
922  float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
923  int ColumnsCurrent;
924  int ColumnsCount;
925  ImVec2 ColumnsStartPos;
926  float ColumnsCellMinY;
927  float ColumnsCellMaxY;
928  bool ColumnsShowBorders;
929  ImGuiID ColumnsSetID;
930  ImVector<float> ColumnsOffsetsT; // Columns offset normalized 0.0 (far left) -> 1.0 (far right)
931 
932  ImGuiDrawContext()
933  {
934  CursorPos = CursorPosPrevLine = CursorStartPos = ImVec2(0.0f, 0.0f);
935  CurrentLineHeight = PrevLineHeight = 0.0f;
936  LogLineHeight = -1.0f;
937  TreeDepth = 0;
938  LastItemID = 0;
939  LastItemAabb = ImGuiAabb(0.0f,0.0f,0.0f,0.0f);
940  LastItemHovered = false;
941  StateStorage = NULL;
942 
943  ColumnsStartX = 0.0f;
944  ColumnsOffsetX = 0.0f;
945  ColumnsCurrent = 0;
946  ColumnsCount = 1;
947  ColumnsStartPos = ImVec2(0.0f, 0.0f);
948  ColumnsCellMinY = ColumnsCellMaxY = 0.0f;
949  ColumnsShowBorders = true;
950  ColumnsSetID = 0;
951  }
952 };
953 
954 // Internal state of the currently focused/edited text input box
955 struct ImGuiTextEditState
956 {
957  ImGuiID Id; // widget id owning the text state
958  ImWchar Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
959  char InitialText[1024*4+1]; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
960  size_t CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
961  size_t BufSizeA; // end-user buffer size, <= 1024 (or increase above)
962  float Width; // widget width
963  float ScrollX;
964  STB_TexteditState StbState;
965  float CursorAnim;
966  ImVec2 InputCursorScreenPos; // Cursor position in screen space to be used by IME callback.
967  bool SelectedAllMouseLock;
968  ImFont* Font;
969  float FontSize;
970 
971  ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
972 
973  void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
974  bool CursorIsVisible() const { return CursorAnim <= 0.0f || fmodf(CursorAnim, 1.20f) <= 0.80f; } // Blinking
975  bool HasSelection() const { return StbState.select_start != StbState.select_end; }
976  void SelectAll() { StbState.select_start = 0; StbState.select_end = (int)ImStrlenW(Text); StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
977 
978  void OnKeyPressed(int key);
979  void UpdateScrollOffset();
980  ImVec2 CalcDisplayOffsetFromCharIdx(int i) const;
981 
982  // Static functions because they are used to render non-focused instances of a text input box
983  static const char* GetTextPointerClippedA(ImFont* font, float font_size, const char* text, float width, ImVec2* out_text_size = NULL);
984  static const ImWchar* GetTextPointerClippedW(ImFont* font, float font_size, const ImWchar* text, float width, ImVec2* out_text_size = NULL);
985  static void RenderTextScrolledClipped(ImFont* font, float font_size, const char* text, ImVec2 pos_base, float width, float scroll_x);
986 };
987 
988 // Data saved in imgui.ini file
989 struct ImGuiIniData
990 {
991  char* Name;
992  ImGuiID ID;
993  ImVec2 Pos;
994  ImVec2 Size;
995  bool Collapsed;
996 
997  ImGuiIniData() { memset(this, 0, sizeof(*this)); }
998  ~ImGuiIniData() { if (Name) { ImGui::MemFree(Name); Name = NULL; } }
999 };
1000 
1001 // Main state for ImGui
1002 struct ImGuiState
1003 {
1004  bool Initialized;
1005  ImGuiIO IO;
1006  ImGuiStyle Style;
1007  ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
1008  float FontSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters.
1009  ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvForWhite
1010 
1011  float Time;
1012  int FrameCount;
1013  int FrameCountRendered;
1014  ImVector<ImGuiWindow*> Windows;
1015  ImGuiWindow* CurrentWindow; // Being drawn into
1016  ImVector<ImGuiWindow*> CurrentWindowStack;
1017  ImGuiWindow* FocusedWindow; // Will catch keyboard inputs
1018  ImGuiWindow* HoveredWindow; // Will catch mouse inputs
1019  ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
1020  ImGuiID HoveredId;
1021  ImGuiID ActiveId;
1022  ImGuiID ActiveIdPreviousFrame;
1023  bool ActiveIdIsAlive;
1024  bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction.
1025  ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Only valid if ActiveID is the "#MOVE" identifier of a window.
1026  float SettingsDirtyTimer;
1027  ImVector<ImGuiIniData*> Settings;
1028  ImVector<ImGuiColMod> ColorModifiers;
1029  ImVector<ImGuiStyleMod> StyleModifiers;
1030  ImVector<ImFont*> FontStack;
1031 
1032  ImVec2 SetNextWindowPosVal;
1033  ImGuiSetCond SetNextWindowPosCond;
1034  ImVec2 SetNextWindowSizeVal;
1035  ImGuiSetCond SetNextWindowSizeCond;
1036  bool SetNextWindowCollapsedVal;
1037  ImGuiSetCond SetNextWindowCollapsedCond;
1038  bool SetNextWindowFocus;
1039  bool SetNextTreeNodeOpenedVal;
1040  ImGuiSetCond SetNextTreeNodeOpenedCond;
1041 
1042  // Render
1043  ImVector<ImDrawList*> RenderDrawLists;
1044  ImVector<ImGuiWindow*> RenderSortedWindows;
1045 
1046  // Widget state
1047  ImGuiTextEditState InputTextState;
1048  ImGuiID SliderAsInputTextId;
1049  ImGuiStorage ColorEditModeStorage; // for user selection
1050  ImGuiID ActiveComboID;
1051  float ScrollbarClickDeltaToGrabCenter; // distance between mouse and center of grab box, normalized in parent space
1052  char Tooltip[1024];
1053  char* PrivateClipboard; // if no custom clipboard handler is defined
1054 
1055  // Logging
1056  bool LogEnabled;
1057  FILE* LogFile;
1058  ImGuiTextBuffer* LogClipboard; // pointer so our GImGui static constructor doesn't call heap allocators.
1059  int LogStartDepth;
1060  int LogAutoExpandMaxDepth;
1061 
1062  // Misc
1063  float FramerateSecPerFrame[120]; // calculate estimate of framerate for user
1064  int FramerateSecPerFrameIdx;
1065  float FramerateSecPerFrameAccum;
1066 
1067  ImGuiState()
1068  {
1069  Initialized = false;
1070  Font = NULL;
1071  FontSize = 0.0f;
1072  FontTexUvWhitePixel = ImVec2(0.0f, 0.0f);
1073 
1074  Time = 0.0f;
1075  FrameCount = 0;
1076  FrameCountRendered = -1;
1077  CurrentWindow = NULL;
1078  FocusedWindow = NULL;
1079  HoveredWindow = NULL;
1080  HoveredRootWindow = NULL;
1081  HoveredId = 0;
1082  ActiveId = 0;
1083  ActiveIdPreviousFrame = 0;
1084  ActiveIdIsAlive = false;
1085  ActiveIdIsFocusedOnly = false;
1086  MovedWindow = NULL;
1087  SettingsDirtyTimer = 0.0f;
1088 
1089  SetNextWindowPosVal = ImVec2(0.0f, 0.0f);
1090  SetNextWindowPosCond = 0;
1091  SetNextWindowSizeVal = ImVec2(0.0f, 0.0f);
1092  SetNextWindowSizeCond = 0;
1093  SetNextWindowCollapsedVal = false;
1094  SetNextWindowCollapsedCond = 0;
1095  SetNextWindowFocus = false;
1096  SetNextTreeNodeOpenedVal = false;
1097  SetNextTreeNodeOpenedCond = 0;
1098 
1099  SliderAsInputTextId = 0;
1100  ActiveComboID = 0;
1101  ScrollbarClickDeltaToGrabCenter = 0.0f;
1102  memset(Tooltip, 0, sizeof(Tooltip));
1103  PrivateClipboard = NULL;
1104 
1105  LogEnabled = false;
1106  LogFile = NULL;
1107  LogClipboard = NULL;
1108  LogStartDepth = 0;
1109  LogAutoExpandMaxDepth = 2;
1110 
1111  memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
1112  FramerateSecPerFrameIdx = 0;
1113  FramerateSecPerFrameAccum = 0.0f;
1114  }
1115 };
1116 
1117 static ImGuiState GImDefaultState; // Internal state storage
1118 static ImGuiState* GImGui = &GImDefaultState; // We access everything through this pointer. NB: this pointer is always assumed to be != NULL
1119 
1120 struct ImGuiWindow
1121 {
1122  char* Name;
1123  ImGuiID ID;
1124  ImGuiWindowFlags Flags;
1125  ImVec2 PosFloat;
1126  ImVec2 Pos; // Position rounded-up to nearest pixel
1127  ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
1128  ImVec2 SizeFull; // Size when non collapsed
1129  ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame
1130  ImVec2 SizeContentsCurrent; // Size of contents, currently extending
1131  float ScrollY;
1132  float NextScrollY;
1133  bool ScrollbarY;
1134  bool Visible; // Set to true on Begin()
1135  bool Accessed; // Set to true when any widget access the current window
1136  bool Collapsed; // Set when collapsing window to become only title-bar
1137  bool SkipItems; // == Visible && !Collapsed
1138  int AutoFitFrames;
1139  bool AutoFitOnlyGrows;
1140  int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call is allowed with this particular flag.
1141  int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call is allowed with this particular flag.
1142  int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call is allowed with this particular flag.
1143 
1144  ImGuiDrawContext DC;
1145  ImVector<ImGuiID> IDStack;
1146  ImVector<ImVec4> ClipRectStack; // Scissoring / clipping rectangle. x1, y1, x2, y2.
1147  ImGuiAabb ClippedAabb; // = ClipRectStack.front() after setup in Begin()
1148  int LastFrameDrawn;
1149  float ItemWidthDefault;
1150  ImGuiStorage StateStorage;
1151  float FontWindowScale; // Scale multiplier per-window
1152  ImDrawList* DrawList;
1153  ImGuiWindow* RootWindow;
1154 
1155  // Focus
1156  int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
1157  int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
1158  int FocusIdxAllRequestCurrent; // Item being requested for focus
1159  int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
1160  int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
1161  int FocusIdxTabRequestNext; // "
1162 
1163 public:
1164  ImGuiWindow(const char* name);
1165  ~ImGuiWindow();
1166 
1167  ImGuiID GetID(const char* str);
1168  ImGuiID GetID(const void* ptr);
1169 
1170  void AddToRenderList();
1171  bool FocusItemRegister(bool is_active, bool tab_stop = true); // Return true if focus is requested
1172  void FocusItemUnregister();
1173 
1174  ImGuiAabb Aabb() const { return ImGuiAabb(Pos, Pos+Size); }
1175  ImFont* Font() const { return GImGui->Font; }
1176  float FontSize() const { return GImGui->FontSize * FontWindowScale; }
1177  ImVec2 CursorPos() const { return DC.CursorPos; }
1178  float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0 : FontSize() + GImGui->Style.FramePadding.y * 2.0f; }
1179  ImGuiAabb TitleBarAabb() const { return ImGuiAabb(Pos, Pos + ImVec2(SizeFull.x, TitleBarHeight())); }
1180  ImVec2 WindowPadding() const { return ((Flags & ImGuiWindowFlags_ChildWindow) && !(Flags & ImGuiWindowFlags_ShowBorders)) ? ImVec2(0,0) : GImGui->Style.WindowPadding; }
1181  ImU32 Color(ImGuiCol idx, float a=1.f) const { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * a; return ImGui::ColorConvertFloat4ToU32(c); }
1182  ImU32 Color(const ImVec4& col) const { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); }
1183 };
1184 
1185 static inline ImGuiWindow* GetCurrentWindow()
1186 {
1187  ImGuiState& g = *GImGui;
1188  IM_ASSERT(g.CurrentWindow != NULL); // ImGui::NewFrame() hasn't been called yet?
1189  g.CurrentWindow->Accessed = true;
1190  return g.CurrentWindow;
1191 }
1192 
1193 static inline ImGuiWindow* GetParentWindow()
1194 {
1195  ImGuiState& g = *GImGui;
1196  IM_ASSERT(g.CurrentWindowStack.size() >= 2);
1197  return g.CurrentWindowStack[g.CurrentWindowStack.size() - 2];
1198 }
1199 
1200 static void SetActiveId(ImGuiID id)
1201 {
1202  ImGuiState& g = *GImGui;
1203  g.ActiveId = id;
1204  g.ActiveIdIsFocusedOnly = false;
1205 }
1206 
1207 static void RegisterAliveId(const ImGuiID& id)
1208 {
1209  ImGuiState& g = *GImGui;
1210  if (g.ActiveId == id)
1211  g.ActiveIdIsAlive = true;
1212 }
1213 
1214 //-----------------------------------------------------------------------------
1215 
1216 // Helper: Key->value storage
1218 {
1219  Data.clear();
1220 }
1221 
1222 // std::lower_bound but without the bullshit
1224 {
1227  int count = (int)(last - first);
1228  while (count > 0)
1229  {
1230  int count2 = count / 2;
1231  ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
1232  if (mid->key < key)
1233  {
1234  first = ++mid;
1235  count -= count2 + 1;
1236  }
1237  else
1238  {
1239  count = count2;
1240  }
1241  }
1242  return first;
1243 }
1244 
1245 int ImGuiStorage::GetInt(ImU32 key, int default_val) const
1246 {
1248  if (it == Data.end() || it->key != key)
1249  return default_val;
1250  return it->val_i;
1251 }
1252 
1253 float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
1254 {
1256  if (it == Data.end() || it->key != key)
1257  return default_val;
1258  return it->val_f;
1259 }
1260 
1262 {
1264  if (it == Data.end() || it->key != key)
1265  return NULL;
1266  return it->val_p;
1267 }
1268 
1269 // References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
1270 int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
1271 {
1272  ImVector<Pair>::iterator it = LowerBound(Data, key);
1273  if (it == Data.end() || it->key != key)
1274  it = Data.insert(it, Pair(key, default_val));
1275  return &it->val_i;
1276 }
1277 
1278 float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
1279 {
1280  ImVector<Pair>::iterator it = LowerBound(Data, key);
1281  if (it == Data.end() || it->key != key)
1282  it = Data.insert(it, Pair(key, default_val));
1283  return &it->val_f;
1284 }
1285 
1286 // FIXME-OPT: Wasting CPU because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
1287 // However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed.
1288 void ImGuiStorage::SetInt(ImU32 key, int val)
1289 {
1290  ImVector<Pair>::iterator it = LowerBound(Data, key);
1291  if (it == Data.end() || it->key != key)
1292  {
1293  Data.insert(it, Pair(key, val));
1294  return;
1295  }
1296  it->val_i = val;
1297 }
1298 
1299 void ImGuiStorage::SetFloat(ImU32 key, float val)
1300 {
1301  ImVector<Pair>::iterator it = LowerBound(Data, key);
1302  if (it == Data.end() || it->key != key)
1303  {
1304  Data.insert(it, Pair(key, val));
1305  return;
1306  }
1307  it->val_f = val;
1308 }
1309 
1310 void ImGuiStorage::SetVoidPtr(ImU32 key, void* val)
1311 {
1312  ImVector<Pair>::iterator it = LowerBound(Data, key);
1313  if (it == Data.end() || it->key != key)
1314  {
1315  Data.insert(it, Pair(key, val));
1316  return;
1317  }
1318  it->val_p = val;
1319 }
1320 
1322 {
1323  for (size_t i = 0; i < Data.size(); i++)
1324  Data[i].val_i = v;
1325 }
1326 
1327 //-----------------------------------------------------------------------------
1328 
1329 // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
1330 ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
1331 {
1332  if (default_filter)
1333  {
1334  ImFormatString(InputBuf, IM_ARRAYSIZE(InputBuf), "%s", default_filter);
1335  Build();
1336  }
1337  else
1338  {
1339  InputBuf[0] = 0;
1340  CountGrep = 0;
1341  }
1342 }
1343 
1344 void ImGuiTextFilter::Draw(const char* label, float width)
1345 {
1346  if (width > 0.0f)
1347  ImGui::PushItemWidth(width);
1348  ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
1349  if (width > 0.0f)
1351  Build();
1352 }
1353 
1355 {
1356  out.resize(0);
1357  const char* wb = b;
1358  const char* we = wb;
1359  while (we < e)
1360  {
1361  if (*we == separator)
1362  {
1363  out.push_back(TextRange(wb, we));
1364  wb = we + 1;
1365  }
1366  we++;
1367  }
1368  if (wb != we)
1369  out.push_back(TextRange(wb, we));
1370 }
1371 
1373 {
1374  Filters.resize(0);
1375  TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
1376  input_range.split(',', Filters);
1377 
1378  CountGrep = 0;
1379  for (size_t i = 0; i != Filters.size(); i++)
1380  {
1381  Filters[i].trim_blanks();
1382  if (Filters[i].empty())
1383  continue;
1384  if (Filters[i].front() != '-')
1385  CountGrep += 1;
1386  }
1387 }
1388 
1389 bool ImGuiTextFilter::PassFilter(const char* val) const
1390 {
1391  if (Filters.empty())
1392  return true;
1393 
1394  if (val == NULL)
1395  val = "";
1396 
1397  for (size_t i = 0; i != Filters.size(); i++)
1398  {
1399  const TextRange& f = Filters[i];
1400  if (f.empty())
1401  continue;
1402  if (f.front() == '-')
1403  {
1404  // Subtract
1405  if (ImStristr(val, f.begin()+1, f.end()) != NULL)
1406  return false;
1407  }
1408  else
1409  {
1410  // Grep
1411  if (ImStristr(val, f.begin(), f.end()) != NULL)
1412  return true;
1413  }
1414  }
1415 
1416  // Implicit * grep
1417  if (CountGrep == 0)
1418  return true;
1419 
1420  return false;
1421 }
1422 
1423 //-----------------------------------------------------------------------------
1424 
1425 // On some platform vsnprintf() takes va_list by reference and modifies it.
1426 // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
1427 #ifndef va_copy
1428 #define va_copy(dest, src) (dest = src)
1429 #endif
1430 
1431 // Helper: Text buffer for logging/accumulating text
1432 void ImGuiTextBuffer::appendv(const char* fmt, va_list args)
1433 {
1434  va_list args_copy;
1435  va_copy(args_copy, args);
1436 
1437  int len = vsnprintf(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
1438  if (len <= 0)
1439  return;
1440 
1441  const size_t write_off = Buf.size();
1442  const size_t needed_sz = write_off + (size_t)len;
1443  if (write_off + (size_t)len >= Buf.capacity())
1444  {
1445  const size_t double_capacity = Buf.capacity() * 2;
1446  Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);
1447  }
1448 
1449  Buf.resize(needed_sz);
1450  ImFormatStringV(&Buf[write_off] - 1, (size_t)len+1, fmt, args_copy);
1451 }
1452 
1453 void ImGuiTextBuffer::append(const char* fmt, ...)
1454 {
1455  va_list args;
1456  va_start(args, fmt);
1457  appendv(fmt, args);
1458  va_end(args);
1459 }
1460 
1461 //-----------------------------------------------------------------------------
1462 
1463 ImGuiWindow::ImGuiWindow(const char* name)
1464 {
1465  Name = ImStrdup(name);
1466  ID = ImHash(name, 0);
1467  IDStack.push_back(ID);
1468 
1469  Flags = 0;
1470  PosFloat = Pos = ImVec2(0.0f, 0.0f);
1471  Size = SizeFull = ImVec2(0.0f, 0.0f);
1472  SizeContents = SizeContentsCurrent = ImVec2(0.0f, 0.0f);
1473  ScrollY = 0.0f;
1474  NextScrollY = 0.0f;
1475  ScrollbarY = false;
1476  Visible = false;
1477  Accessed = false;
1478  Collapsed = false;
1479  SkipItems = false;
1480  AutoFitFrames = -1;
1481  AutoFitOnlyGrows = false;
1482  SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver;
1483 
1484  LastFrameDrawn = -1;
1485  ItemWidthDefault = 0.0f;
1486  FontWindowScale = 1.0f;
1487 
1488  if (ImLengthSqr(Size) < 0.00001f)
1489  {
1490  AutoFitFrames = 2;
1491  AutoFitOnlyGrows = true;
1492  }
1493 
1494  DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
1495  new(DrawList) ImDrawList();
1496  RootWindow = NULL;
1497 
1498  FocusIdxAllCounter = FocusIdxTabCounter = -1;
1499  FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = IM_INT_MAX;
1500  FocusIdxAllRequestNext = FocusIdxTabRequestNext = IM_INT_MAX;
1501 }
1502 
1503 ImGuiWindow::~ImGuiWindow()
1504 {
1505  DrawList->~ImDrawList();
1506  ImGui::MemFree(DrawList);
1507  DrawList = NULL;
1508  ImGui::MemFree(Name);
1509  Name = NULL;
1510 }
1511 
1512 ImGuiID ImGuiWindow::GetID(const char* str)
1513 {
1514  ImGuiID seed = IDStack.back();
1515  const ImGuiID id = ImHash(str, 0, seed);
1516  RegisterAliveId(id);
1517  return id;
1518 }
1519 
1520 ImGuiID ImGuiWindow::GetID(const void* ptr)
1521 {
1522  ImGuiID seed = IDStack.back();
1523  const ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
1524  RegisterAliveId(id);
1525  return id;
1526 }
1527 
1528 bool ImGuiWindow::FocusItemRegister(bool is_active, bool tab_stop)
1529 {
1530  ImGuiState& g = *GImGui;
1531  ImGuiWindow* window = GetCurrentWindow();
1532 
1533  const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus.back();
1534  FocusIdxAllCounter++;
1535  if (allow_keyboard_focus)
1536  FocusIdxTabCounter++;
1537 
1538  // Process keyboard input at this point: TAB, Shift-TAB switch focus
1539  // We can always TAB out of a widget that doesn't allow tabbing in.
1540  if (tab_stop && FocusIdxAllRequestNext == IM_INT_MAX && FocusIdxTabRequestNext == IM_INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab))
1541  {
1542  // Modulo on index will be applied at the end of frame once we've got the total counter of items.
1543  FocusIdxTabRequestNext = FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1);
1544  }
1545 
1546  if (FocusIdxAllCounter == FocusIdxAllRequestCurrent)
1547  return true;
1548 
1549  if (allow_keyboard_focus)
1550  if (FocusIdxTabCounter == FocusIdxTabRequestCurrent)
1551  return true;
1552 
1553  return false;
1554 }
1555 
1556 void ImGuiWindow::FocusItemUnregister()
1557 {
1558  FocusIdxAllCounter--;
1559  FocusIdxTabCounter--;
1560 }
1561 
1562 void ImGuiWindow::AddToRenderList()
1563 {
1564  ImGuiState& g = *GImGui;
1565 
1566  if (!DrawList->commands.empty() && !DrawList->vtx_buffer.empty())
1567  {
1568  if (DrawList->commands.back().vtx_count == 0)
1569  DrawList->commands.pop_back();
1570  g.RenderDrawLists.push_back(DrawList);
1571  }
1572  for (size_t i = 0; i < DC.ChildWindows.size(); i++)
1573  {
1574  ImGuiWindow* child = DC.ChildWindows[i];
1575  if (child->Visible) // clipped children may have been marked not Visible
1576  child->AddToRenderList();
1577  }
1578 }
1579 
1580 //-----------------------------------------------------------------------------
1581 
1582 void* ImGui::MemAlloc(size_t sz)
1583 {
1584  return GImGui->IO.MemAllocFn(sz);
1585 }
1586 
1587 void ImGui::MemFree(void* ptr)
1588 {
1589  return GImGui->IO.MemFreeFn(ptr);
1590 }
1591 
1592 static ImGuiIniData* FindWindowSettings(const char* name)
1593 {
1594  ImGuiState& g = *GImGui;
1595  ImGuiID id = ImHash(name, 0);
1596  for (size_t i = 0; i != g.Settings.size(); i++)
1597  {
1598  ImGuiIniData* ini = g.Settings[i];
1599  if (ini->ID == id)
1600  return ini;
1601  }
1602  return NULL;
1603 }
1604 
1605 static ImGuiIniData* AddWindowSettings(const char* name)
1606 {
1607  ImGuiIniData* ini = (ImGuiIniData*)ImGui::MemAlloc(sizeof(ImGuiIniData));
1608  new(ini) ImGuiIniData();
1609  ini->Name = ImStrdup(name);
1610  ini->ID = ImHash(name, 0);
1611  ini->Collapsed = false;
1612  ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
1613  ini->Size = ImVec2(0,0);
1614  GImGui->Settings.push_back(ini);
1615  return ini;
1616 }
1617 
1618 // Zero-tolerance, poor-man .ini parsing
1619 // FIXME: Write something less rubbish
1620 static void LoadSettings()
1621 {
1622  ImGuiState& g = *GImGui;
1623  const char* filename = g.IO.IniFilename;
1624  if (!filename)
1625  return;
1626 
1627  char* file_data;
1628  size_t file_size;
1629  if (!ImLoadFileToMemory(filename, "rb", (void**)&file_data, &file_size, 1))
1630  return;
1631 
1632  ImGuiIniData* settings = NULL;
1633  const char* buf_end = file_data + file_size;
1634  for (const char* line_start = file_data; line_start < buf_end; )
1635  {
1636  const char* line_end = line_start;
1637  while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
1638  line_end++;
1639 
1640  if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
1641  {
1642  char name[64];
1643  ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1);
1644  settings = FindWindowSettings(name);
1645  if (!settings)
1646  settings = AddWindowSettings(name);
1647  }
1648  else if (settings)
1649  {
1650  float x, y;
1651  int i;
1652  if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2)
1653  settings->Pos = ImVec2(x, y);
1654  else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2)
1655  settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);
1656  else if (sscanf(line_start, "Collapsed=%d", &i) == 1)
1657  settings->Collapsed = (i != 0);
1658  }
1659 
1660  line_start = line_end+1;
1661  }
1662 
1663  ImGui::MemFree(file_data);
1664 }
1665 
1666 static void SaveSettings()
1667 {
1668  ImGuiState& g = *GImGui;
1669  const char* filename = g.IO.IniFilename;
1670  if (!filename)
1671  return;
1672 
1673  // Gather data from windows that were active during this session
1674  for (size_t i = 0; i != g.Windows.size(); i++)
1675  {
1676  ImGuiWindow* window = g.Windows[i];
1677  if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
1678  continue;
1679  ImGuiIniData* settings = FindWindowSettings(window->Name);
1680  settings->Pos = window->Pos;
1681  settings->Size = window->SizeFull;
1682  settings->Collapsed = window->Collapsed;
1683  }
1684 
1685  // Write .ini file
1686  // If a window wasn't opened in this session we preserve its settings
1687  FILE* f = fopen(filename, "wt");
1688  if (!f)
1689  return;
1690  for (size_t i = 0; i != g.Settings.size(); i++)
1691  {
1692  const ImGuiIniData* settings = g.Settings[i];
1693  if (settings->Pos.x == FLT_MAX)
1694  continue;
1695  const char* name = settings->Name;
1696  if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
1697  name = p;
1698  fprintf(f, "[%s]\n", name);
1699  fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
1700  fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
1701  fprintf(f, "Collapsed=%d\n", settings->Collapsed);
1702  fprintf(f, "\n");
1703  }
1704 
1705  fclose(f);
1706 }
1707 
1708 static void MarkSettingsDirty()
1709 {
1710  ImGuiState& g = *GImGui;
1711 
1712  if (g.SettingsDirtyTimer <= 0.0f)
1713  g.SettingsDirtyTimer = g.IO.IniSavingRate;
1714 }
1715 
1716 // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
1717 // Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
1719 {
1720  return GImGui;
1721 }
1722 
1724 {
1725  return sizeof(ImGuiState);
1726 }
1727 
1728 void ImGui::SetInternalState(void* state, bool construct)
1729 {
1730  if (construct)
1731  new (state) ImGuiState();
1732 
1733  GImGui = (ImGuiState*)state;
1734 }
1735 
1737 {
1738  return GImGui->IO;
1739 }
1740 
1742 {
1743  return GImGui->Style;
1744 }
1745 
1747 {
1748  ImGuiState& g = *GImGui;
1749 
1750  // Check user data
1751  IM_ASSERT(g.IO.DeltaTime > 0.0f);
1752  IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
1753  IM_ASSERT(g.IO.RenderDrawListsFn != NULL); // Must be implemented
1754  IM_ASSERT(g.IO.Fonts->Fonts.size() > 0); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
1755  IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
1756 
1757  if (!g.Initialized)
1758  {
1759  // Initialize on first frame
1760  g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));
1761  new(g.LogClipboard) ImGuiTextBuffer();
1762 
1763  IM_ASSERT(g.Settings.empty());
1764  LoadSettings();
1765  g.Initialized = true;
1766  }
1767 
1768  SetFont(g.IO.Fonts->Fonts[0]);
1769 
1770  g.Time += g.IO.DeltaTime;
1771  g.FrameCount += 1;
1772  g.Tooltip[0] = '\0';
1773 
1774  // Update inputs state
1775  if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0)
1776  g.IO.MousePos = ImVec2(-9999.0f, -9999.0f);
1777  if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta
1778  g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
1779  else
1780  g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
1781  g.IO.MousePosPrev = g.IO.MousePos;
1782  for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
1783  {
1784  g.IO.MouseDownTime[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownTime[i] < 0.0f ? 0.0f : g.IO.MouseDownTime[i] + g.IO.DeltaTime) : -1.0f;
1785  g.IO.MouseClicked[i] = (g.IO.MouseDownTime[i] == 0.0f);
1786  g.IO.MouseDoubleClicked[i] = false;
1787  if (g.IO.MouseClicked[i])
1788  {
1789  if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime)
1790  {
1791  if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
1792  g.IO.MouseDoubleClicked[i] = true;
1793  g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click
1794  }
1795  else
1796  {
1797  g.IO.MouseClickedTime[i] = g.Time;
1798  g.IO.MouseClickedPos[i] = g.IO.MousePos;
1799  }
1800  }
1801  }
1802  for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
1803  g.IO.KeysDownTime[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownTime[i] < 0.0f ? 0.0f : g.IO.KeysDownTime[i] + g.IO.DeltaTime) : -1.0f;
1804 
1805  // Calculate frame-rate for the user, as a purely luxurious feature
1806  g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
1807  g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
1808  g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
1809  g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame));
1810 
1811  // Clear reference to active widget if the widget isn't alive anymore
1812  g.HoveredId = 0;
1813  if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
1814  SetActiveId(0);
1815  g.ActiveIdPreviousFrame = g.ActiveId;
1816  g.ActiveIdIsAlive = false;
1817  if (!g.ActiveId)
1818  g.MovedWindow = NULL;
1819 
1820  // Delay saving settings so we don't spam disk too much
1821  if (g.SettingsDirtyTimer > 0.0f)
1822  {
1823  g.SettingsDirtyTimer -= g.IO.DeltaTime;
1824  if (g.SettingsDirtyTimer <= 0.0f)
1825  SaveSettings();
1826  }
1827 
1828  // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow
1829  g.HoveredWindow = FindHoveredWindow(g.IO.MousePos, false);
1830  if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow))
1831  g.HoveredRootWindow = g.HoveredWindow->RootWindow;
1832  else
1833  g.HoveredRootWindow = FindHoveredWindow(g.IO.MousePos, true);
1834 
1835  // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application.
1836  // When clicking outside of a window we assume the click is owned by the application and won't request capture.
1837  int mouse_earliest_button_down = -1;
1838  for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
1839  {
1840  if (g.IO.MouseClicked[i])
1841  g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL);
1842  if (g.IO.MouseDown[i])
1843  if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i])
1844  mouse_earliest_button_down = i;
1845  }
1846  bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down];
1847  g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (g.ActiveId != 0);
1848  g.IO.WantCaptureKeyboard = (g.ActiveId != 0);
1849 
1850  // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
1851  if (mouse_owned_by_application)
1852  g.HoveredWindow = g.HoveredRootWindow = NULL;
1853 
1854  // Scale & Scrolling
1855  if (g.HoveredWindow && g.IO.MouseWheel != 0.0f)
1856  {
1857  ImGuiWindow* window = g.HoveredWindow;
1858  if (g.IO.KeyCtrl)
1859  {
1860  if (g.IO.FontAllowUserScaling)
1861  {
1862  // Zoom / Scale window
1863  float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
1864  float scale = new_font_scale / window->FontWindowScale;
1865  window->FontWindowScale = new_font_scale;
1866 
1867  const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
1868  window->Pos += offset;
1869  window->PosFloat += offset;
1870  window->Size *= scale;
1871  window->SizeFull *= scale;
1872  }
1873  }
1874  else
1875  {
1876  // Scroll
1877  if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse))
1878  {
1879  const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5;
1880  window->NextScrollY -= g.IO.MouseWheel * window->FontSize() * scroll_lines;
1881  }
1882  }
1883  }
1884 
1885  // Pressing TAB activate widget focus
1886  // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.
1887  if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Visible && IsKeyPressedMap(ImGuiKey_Tab, false))
1888  {
1889  g.FocusedWindow->FocusIdxTabRequestNext = 0;
1890  }
1891 
1892  // Mark all windows as not visible
1893  for (size_t i = 0; i != g.Windows.size(); i++)
1894  {
1895  ImGuiWindow* window = g.Windows[i];
1896  window->Visible = false;
1897  window->Accessed = false;
1898  }
1899 
1900  // No window should be open at the beginning of the frame.
1901  // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
1902  g.CurrentWindowStack.resize(0);
1903 
1904  // Create implicit window - we will only render it if the user has added something to it.
1905  ImGui::Begin("Debug", NULL, ImVec2(400,400));
1906 }
1907 
1908 // NB: behaviour of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations.
1910 {
1911  ImGuiState& g = *GImGui;
1912  if (!g.Initialized)
1913  return;
1914 
1915  SaveSettings();
1916 
1917  for (size_t i = 0; i < g.Windows.size(); i++)
1918  {
1919  g.Windows[i]->~ImGuiWindow();
1920  ImGui::MemFree(g.Windows[i]);
1921  }
1922  g.Windows.clear();
1923  g.CurrentWindowStack.clear();
1924  g.RenderDrawLists.clear();
1925  g.FocusedWindow = NULL;
1926  g.HoveredWindow = NULL;
1927  g.HoveredRootWindow = NULL;
1928  for (size_t i = 0; i < g.Settings.size(); i++)
1929  {
1930  g.Settings[i]->~ImGuiIniData();
1931  ImGui::MemFree(g.Settings[i]);
1932  }
1933  g.Settings.clear();
1934  g.ColorModifiers.clear();
1935  g.StyleModifiers.clear();
1936  g.FontStack.clear();
1937  g.ColorEditModeStorage.Clear();
1938  if (g.LogFile && g.LogFile != stdout)
1939  {
1940  fclose(g.LogFile);
1941  g.LogFile = NULL;
1942  }
1943  g.IO.Fonts->Clear();
1944 
1945  if (g.PrivateClipboard)
1946  {
1947  ImGui::MemFree(g.PrivateClipboard);
1948  g.PrivateClipboard = NULL;
1949  }
1950 
1951  if (g.LogClipboard)
1952  {
1953  g.LogClipboard->~ImGuiTextBuffer();
1954  ImGui::MemFree(g.LogClipboard);
1955  }
1956 
1957  g.Initialized = false;
1958 }
1959 
1960 // FIXME: Add a more explicit sort order in the window structure.
1961 static int ChildWindowComparer(const void* lhs, const void* rhs)
1962 {
1963  const ImGuiWindow* a = *(const ImGuiWindow**)lhs;
1964  const ImGuiWindow* b = *(const ImGuiWindow**)rhs;
1965  if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
1966  return d;
1967  if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox))
1968  return d;
1969  return 0;
1970 }
1971 
1972 static void AddWindowToSortedBuffer(ImGuiWindow* window, ImVector<ImGuiWindow*>& sorted_windows)
1973 {
1974  sorted_windows.push_back(window);
1975  if (window->Visible)
1976  {
1977  const size_t count = window->DC.ChildWindows.size();
1978  if (count > 1)
1979  qsort(window->DC.ChildWindows.begin(), count, sizeof(ImGuiWindow*), ChildWindowComparer);
1980  for (size_t i = 0; i < count; i++)
1981  {
1982  ImGuiWindow* child = window->DC.ChildWindows[i];
1983  if (child->Visible)
1984  AddWindowToSortedBuffer(child, sorted_windows);
1985  }
1986  }
1987 }
1988 
1989 static void PushClipRect(const ImVec4& clip_rect, bool clipped = true)
1990 {
1991  ImGuiWindow* window = GetCurrentWindow();
1992 
1993  ImVec4 cr = clip_rect;
1994  if (clipped && !window->ClipRectStack.empty())
1995  {
1996  // Clip with existing clip rect
1997  const ImVec4 cur_cr = window->ClipRectStack.back();
1998  cr = ImVec4(ImMax(cr.x, cur_cr.x), ImMax(cr.y, cur_cr.y), ImMin(cr.z, cur_cr.z), ImMin(cr.w, cur_cr.w));
1999  }
2000 
2001  window->ClipRectStack.push_back(cr);
2002  window->DrawList->PushClipRect(cr);
2003 }
2004 
2005 static void PopClipRect()
2006 {
2007  ImGuiWindow* window = GetCurrentWindow();
2008  window->ClipRectStack.pop_back();
2009  window->DrawList->PopClipRect();
2010 }
2011 
2013 {
2014  ImGuiState& g = *GImGui;
2015  IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
2016 
2017  const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount);
2018  g.FrameCountRendered = g.FrameCount;
2019 
2020  if (first_render_of_the_frame)
2021  {
2022  // Hide implicit window if it hasn't been used
2023  IM_ASSERT(g.CurrentWindowStack.size() == 1); // Mismatched Begin/End
2024  if (g.CurrentWindow && !g.CurrentWindow->Accessed)
2025  g.CurrentWindow->Visible = false;
2026  ImGui::End();
2027 
2028  // Select window for move/focus when we're done with all our widgets (we use the root window ID here)
2029  if (g.ActiveId == 0 && g.HoveredId == 0 && g.HoveredRootWindow != NULL && g.IO.MouseClicked[0])
2030  {
2031  IM_ASSERT(g.MovedWindow == NULL);
2032  g.MovedWindow = g.HoveredWindow;
2033  SetActiveId(g.HoveredRootWindow->GetID("#MOVE"));
2034  }
2035 
2036  // Sort the window list so that all child windows are after their parent
2037  // We cannot do that on FocusWindow() because childs may not exist yet
2038  g.RenderSortedWindows.resize(0);
2039  g.RenderSortedWindows.reserve(g.Windows.size());
2040  for (size_t i = 0; i != g.Windows.size(); i++)
2041  {
2042  ImGuiWindow* window = g.Windows[i];
2043  if (window->Flags & ImGuiWindowFlags_ChildWindow) // if a child is visible its parent will add it
2044  if (window->Visible)
2045  continue;
2046  AddWindowToSortedBuffer(window, g.RenderSortedWindows);
2047  }
2048  IM_ASSERT(g.Windows.size() == g.RenderSortedWindows.size()); // we done something wrong
2049  g.Windows.swap(g.RenderSortedWindows);
2050 
2051  // Clear data for next frame
2052  g.IO.MouseWheel = 0.0f;
2053  memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
2054  }
2055 
2056  // Skip render altogether if alpha is 0.0
2057  // Note that vertex buffers have been created, so it is best practice that you don't call Begin/End in the first place.
2058  if (g.Style.Alpha > 0.0f)
2059  {
2060  // Render tooltip
2061  if (g.Tooltip[0])
2062  {
2063  // Use a dummy window to render the tooltip
2065  ImGui::TextUnformatted(g.Tooltip);
2067  }
2068 
2069  // Gather windows to render
2070  g.RenderDrawLists.resize(0);
2071  for (size_t i = 0; i != g.Windows.size(); i++)
2072  {
2073  ImGuiWindow* window = g.Windows[i];
2074  if (window->Visible && (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0)
2075  window->AddToRenderList();
2076  }
2077  for (size_t i = 0; i != g.Windows.size(); i++)
2078  {
2079  ImGuiWindow* window = g.Windows[i];
2080  if (window->Visible && (window->Flags & ImGuiWindowFlags_Tooltip))
2081  window->AddToRenderList();
2082  }
2083 
2084  if (g.IO.MouseDrawCursor)
2085  {
2086  const ImVec2 pos = g.IO.MousePos;
2087  const ImVec2 size = TEX_ATLAS_SIZE_MOUSE_CURSOR;
2088  const ImTextureID tex_id = g.IO.Fonts->TexID;
2089  const ImVec2 tex_uv_scale(1.0f/g.IO.Fonts->TexWidth, 1.0f/g.IO.Fonts->TexHeight);
2090  static ImDrawList draw_list;
2091  draw_list.Clear();
2092  draw_list.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
2093  draw_list.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
2094  draw_list.AddImage(tex_id, pos, pos + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0xFF000000); // Black border
2095  draw_list.AddImage(tex_id, pos, pos + size, TEX_ATLAS_POS_MOUSE_CURSOR_WHITE * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_WHITE + size) * tex_uv_scale, 0xFFFFFFFF); // White fill
2096  g.RenderDrawLists.push_back(&draw_list);
2097  }
2098 
2099  // Render
2100  if (!g.RenderDrawLists.empty())
2101  g.IO.RenderDrawListsFn(&g.RenderDrawLists[0], (int)g.RenderDrawLists.size());
2102  g.RenderDrawLists.resize(0);
2103  }
2104 }
2105 
2106 // Find the optional ## from which we stop displaying text.
2107 static const char* FindTextDisplayEnd(const char* text, const char* text_end = NULL)
2108 {
2109  const char* text_display_end = text;
2110  if (!text_end)
2111  text_end = (const char*)-1;
2112  while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
2113  text_display_end++;
2114  return text_display_end;
2115 }
2116 
2117 // Pass text data straight to log (without being displayed)
2118 void ImGui::LogText(const char* fmt, ...)
2119 {
2120  ImGuiState& g = *GImGui;
2121  if (!g.LogEnabled)
2122  return;
2123 
2124  va_list args;
2125  va_start(args, fmt);
2126  if (g.LogFile)
2127  {
2128  vfprintf(g.LogFile, fmt, args);
2129  }
2130  else
2131  {
2132  g.LogClipboard->appendv(fmt, args);
2133  }
2134  va_end(args);
2135 }
2136 
2137 // Internal version that takes a position to decide on newline placement and pad items according to their depth.
2138 // We split text into individual lines to add current tree level padding
2139 static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end)
2140 {
2141  ImGuiState& g = *GImGui;
2142  ImGuiWindow* window = GetCurrentWindow();
2143 
2144  if (!text_end)
2145  text_end = FindTextDisplayEnd(text, text_end);
2146 
2147  const bool log_new_line = ref_pos.y > window->DC.LogLineHeight+1;
2148  window->DC.LogLineHeight = ref_pos.y;
2149 
2150  const char* text_remaining = text;
2151  if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
2152  g.LogStartDepth = window->DC.TreeDepth;
2153  const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
2154  for (;;)
2155  {
2156  // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
2157  const char* line_end = text_remaining;
2158  while (line_end < text_end)
2159  if (*line_end == '\n')
2160  break;
2161  else
2162  line_end++;
2163  if (line_end >= text_end)
2164  line_end = NULL;
2165 
2166  const bool is_first_line = (text == text_remaining);
2167  bool is_last_line = false;
2168  if (line_end == NULL)
2169  {
2170  is_last_line = true;
2171  line_end = text_end;
2172  }
2173  if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0))
2174  {
2175  const int char_count = (int)(line_end - text_remaining);
2176  if (log_new_line || !is_first_line)
2177  ImGui::LogText(STR_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining);
2178  else
2179  ImGui::LogText(" %.*s", char_count, text_remaining);
2180  }
2181 
2182  if (is_last_line)
2183  break;
2184  text_remaining = line_end + 1;
2185  }
2186 }
2187 
2188 static float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
2189 {
2190  if (wrap_pos_x < 0.0f)
2191  return 0.0f;
2192 
2193  ImGuiWindow* window = GetCurrentWindow();
2194  if (wrap_pos_x == 0.0f)
2195  wrap_pos_x = ImGui::GetContentRegionMax().x;
2196  if (wrap_pos_x > 0.0f)
2197  wrap_pos_x += window->Pos.x; // wrap_pos_x is provided is window local space
2198 
2199  const float wrap_width = wrap_pos_x > 0.0f ? ImMax(wrap_pos_x - pos.x, 0.00001f) : 0.0f;
2200  return wrap_width;
2201 }
2202 
2203 // Internal ImGui functions to render text
2204 // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
2205 static void RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
2206 {
2207  ImGuiState& g = *GImGui;
2208  ImGuiWindow* window = GetCurrentWindow();
2209 
2210  // Hide anything after a '##' string
2211  const char* text_display_end;
2212  if (hide_text_after_hash)
2213  {
2214  text_display_end = FindTextDisplayEnd(text, text_end);
2215  }
2216  else
2217  {
2218  if (!text_end)
2219  text_end = text + strlen(text); // FIXME-OPT
2220  text_display_end = text_end;
2221  }
2222 
2223  const int text_len = (int)(text_display_end - text);
2224  if (text_len > 0)
2225  {
2226  // Render
2227  window->DrawList->AddText(window->Font(), window->FontSize(), pos, window->Color(ImGuiCol_Text), text, text_display_end);
2228 
2229  // Log as text
2230  if (g.LogEnabled)
2231  LogText(pos, text, text_display_end);
2232  }
2233 }
2234 
2235 static void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
2236 {
2237  ImGuiState& g = *GImGui;
2238  ImGuiWindow* window = GetCurrentWindow();
2239 
2240  if (!text_end)
2241  text_end = text + strlen(text); // FIXME-OPT
2242 
2243  const int text_len = (int)(text_end - text);
2244  if (text_len > 0)
2245  {
2246  // Render
2247  window->DrawList->AddText(window->Font(), window->FontSize(), pos, window->Color(ImGuiCol_Text), text, text_end, wrap_width);
2248 
2249  // Log as text
2250  if (g.LogEnabled)
2251  LogText(pos, text, text_end);
2252  }
2253 }
2254 
2255 static void RenderTextClipped(ImVec2 pos, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& clip_max)
2256 {
2257  ImGuiState& g = *GImGui;
2258  ImGuiWindow* window = GetCurrentWindow();
2259 
2260  // Hide anything after a '##' string
2261  const char* text_display_end = FindTextDisplayEnd(text, text_end);
2262  const int text_len = (int)(text_display_end - text);
2263  if (text_len > 0)
2264  {
2265  const ImVec2 text_size = text_size_if_known ? *text_size_if_known : ImGui::CalcTextSize(text, text_display_end, false, 0.0f);
2266 
2267  // Perform CPU side clipping for single clipped element to avoid using scissor state
2268  const bool need_clipping = (pos.x + text_size.x >= clip_max.x) || (pos.y + text_size.y >= clip_max.y);
2269 
2270  // Render
2271  window->DrawList->AddText(window->Font(), window->FontSize(), pos, window->Color(ImGuiCol_Text), text, text_display_end, 0.0f, need_clipping ? &clip_max : NULL);
2272 
2273  // Log as text
2274  if (g.LogEnabled)
2275  LogText(pos, text, text_display_end);
2276  }
2277 }
2278 
2279 // Render a rectangle shaped with optional rounding and borders
2280 static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
2281 {
2282  ImGuiWindow* window = GetCurrentWindow();
2283 
2284  window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
2285  if (border && (window->Flags & ImGuiWindowFlags_ShowBorders))
2286  {
2287  // FIXME: This is the best I've found that works on multiple renderer/back ends. Bit dodgy.
2288  window->DrawList->AddRect(p_min+ImVec2(1.5f,1.5f), p_max+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), rounding);
2289  window->DrawList->AddRect(p_min+ImVec2(0.5f,0.5f), p_max+ImVec2(0,0), window->Color(ImGuiCol_Border), rounding);
2290  }
2291 }
2292 
2293 // Render a triangle to denote expanded/collapsed state
2294 static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale, bool shadow)
2295 {
2296  ImGuiWindow* window = GetCurrentWindow();
2297 
2298  const float h = window->FontSize() * 1.00f;
2299  const float r = h * 0.40f * scale;
2300  ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale);
2301 
2302  ImVec2 a, b, c;
2303  if (opened)
2304  {
2305  center.y -= r*0.25f;
2306  a = center + ImVec2(0,1)*r;
2307  b = center + ImVec2(-0.866f,-0.5f)*r;
2308  c = center + ImVec2(0.866f,-0.5f)*r;
2309  }
2310  else
2311  {
2312  a = center + ImVec2(1,0)*r;
2313  b = center + ImVec2(-0.500f,0.866f)*r;
2314  c = center + ImVec2(-0.500f,-0.866f)*r;
2315  }
2316 
2317  if (shadow && (window->Flags & ImGuiWindowFlags_ShowBorders) != 0)
2318  window->DrawList->AddTriangleFilled(a+ImVec2(2,2), b+ImVec2(2,2), c+ImVec2(2,2), window->Color(ImGuiCol_BorderShadow));
2319  window->DrawList->AddTriangleFilled(a, b, c, window->Color(ImGuiCol_Text));
2320 }
2321 
2322 // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
2323 // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize)
2324 ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
2325 {
2326  ImGuiWindow* window = GetCurrentWindow();
2327 
2328  const char* text_display_end;
2329  if (hide_text_after_double_hash)
2330  text_display_end = FindTextDisplayEnd(text, text_end); // Hide anything after a '##' string
2331  else
2332  text_display_end = text_end;
2333 
2334  ImFont* font = window->Font();
2335  const float font_size = window->FontSize();
2336  ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
2337 
2338  // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field)
2339  const float font_scale = font_size / font->FontSize;
2340  const float character_spacing_x = 1.0f * font_scale;
2341  if (text_size.x > 0.0f)
2342  text_size.x -= character_spacing_x;
2343 
2344  return text_size;
2345 }
2346 
2347 // Helper to calculate coarse clipping of large list of evenly sized items.
2348 // If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU.
2349 // {
2350 // float item_height = ImGui::GetTextLineHeightWithSpacing();
2351 // int display_start, display_end;
2352 // ImGui::CalcListClipping(count, item_height, &display_start, &display_end); // calculate how many to clip/display
2353 // ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (display_start) * item_height); // advance cursor
2354 // for (int i = display_start; i < display_end; i++) // display only visible items
2355 // // TODO: display visible item
2356 // ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (count - display_end) * item_height); // advance cursor
2357 // }
2358 void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
2359 {
2360  ImGuiState& g = *GImGui;
2361  ImGuiWindow* window = GetCurrentWindow();
2362 
2363  if (g.LogEnabled)
2364  {
2365  // If logging is active, do not perform any clipping
2366  *out_items_display_start = 0;
2367  *out_items_display_end = items_count;
2368  return;
2369  }
2370 
2371  const ImVec2 pos = window->DC.CursorPos;
2372  const ImVec4 clip_rect = window->ClipRectStack.back();
2373  const float clip_y1 = clip_rect.y;
2374  const float clip_y2 = clip_rect.w;
2375 
2376  int start = (int)((clip_y1 - pos.y) / items_height);
2377  int end = (int)((clip_y2 - pos.y) / items_height);
2378  start = ImClamp(start, 0, items_count);
2379  end = ImClamp(end + 1, start, items_count);
2380 
2381  *out_items_display_start = start;
2382  *out_items_display_end = end;
2383 }
2384 
2385 // Find window given position, search front-to-back
2386 static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)
2387 {
2388  ImGuiState& g = *GImGui;
2389  for (int i = (int)g.Windows.size()-1; i >= 0; i--)
2390  {
2391  ImGuiWindow* window = g.Windows[(size_t)i];
2392  if (!window->Visible)
2393  continue;
2394  if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
2395  continue;
2396 
2397  // Using the clipped AABB so a child window will typically be clipped by its parent.
2398  ImGuiAabb bb(window->ClippedAabb.Min - g.Style.TouchExtraPadding, window->ClippedAabb.Max + g.Style.TouchExtraPadding);
2399  if (bb.Contains(pos))
2400  return window;
2401  }
2402  return NULL;
2403 }
2404 
2405 // Test if mouse cursor is hovering given aabb
2406 // NB- Box is clipped by our current clip setting
2407 // NB- Expand the aabb to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
2408 static bool IsMouseHoveringBox(const ImGuiAabb& bb)
2409 {
2410  ImGuiState& g = *GImGui;
2411  ImGuiWindow* window = GetCurrentWindow();
2412 
2413  // Clip
2414  ImGuiAabb box_clipped = bb;
2415  if (!window->ClipRectStack.empty())
2416  {
2417  const ImVec4 clip_rect = window->ClipRectStack.back();
2418  box_clipped.Clip(ImGuiAabb(ImVec2(clip_rect.x, clip_rect.y), ImVec2(clip_rect.z, clip_rect.w)));
2419  }
2420 
2421  // Expand for touch input
2422  const ImGuiAabb box_for_touch(box_clipped.Min - g.Style.TouchExtraPadding, box_clipped.Max + g.Style.TouchExtraPadding);
2423  return box_for_touch.Contains(g.IO.MousePos);
2424 }
2425 
2426 bool ImGui::IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max)
2427 {
2428  return IsMouseHoveringBox(ImGuiAabb(box_min, box_max));
2429 }
2430 
2432 {
2433  ImGuiState& g = *GImGui;
2434  ImGuiWindow* window = GetCurrentWindow();
2435  return g.HoveredWindow == window;
2436 }
2437 
2439 {
2440  ImGuiState& g = *GImGui;
2441  return g.HoveredWindow != NULL;
2442 }
2443 
2445 {
2446  return FindHoveredWindow(pos, false) != NULL;
2447 }
2448 
2449 static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
2450 {
2451  ImGuiState& g = *GImGui;
2452  const int key_index = g.IO.KeyMap[key];
2453  return ImGui::IsKeyPressed(key_index, repeat);
2454 }
2455 
2456 bool ImGui::IsKeyPressed(int key_index, bool repeat)
2457 {
2458  ImGuiState& g = *GImGui;
2459  IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
2460  const float t = g.IO.KeysDownTime[key_index];
2461  if (t == 0.0f)
2462  return true;
2463 
2464  // FIXME: Repeat rate should be provided elsewhere?
2465  const float KEY_REPEAT_DELAY = 0.250f;
2466  const float KEY_REPEAT_RATE = 0.020f;
2467  if (repeat && t > KEY_REPEAT_DELAY)
2468  if ((fmodf(t - KEY_REPEAT_DELAY, KEY_REPEAT_RATE) > KEY_REPEAT_RATE*0.5f) != (fmodf(t - KEY_REPEAT_DELAY - g.IO.DeltaTime, KEY_REPEAT_RATE) > KEY_REPEAT_RATE*0.5f))
2469  return true;
2470 
2471  return false;
2472 }
2473 
2474 bool ImGui::IsMouseClicked(int button, bool repeat)
2475 {
2476  ImGuiState& g = *GImGui;
2477  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
2478  const float t = g.IO.MouseDownTime[button];
2479  if (t == 0.0f)
2480  return true;
2481 
2482  // FIXME: Repeat rate should be provided elsewhere?
2483  const float MOUSE_REPEAT_DELAY = 0.250f;
2484  const float MOUSE_REPEAT_RATE = 0.020f;
2485  if (repeat && t > MOUSE_REPEAT_DELAY)
2486  if ((fmodf(t - MOUSE_REPEAT_DELAY, MOUSE_REPEAT_RATE) > MOUSE_REPEAT_RATE*0.5f) != (fmodf(t - MOUSE_REPEAT_DELAY - g.IO.DeltaTime, MOUSE_REPEAT_RATE) > MOUSE_REPEAT_RATE*0.5f))
2487  return true;
2488 
2489  return false;
2490 }
2491 
2493 {
2494  ImGuiState& g = *GImGui;
2495  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
2496  return g.IO.MouseDoubleClicked[button];
2497 }
2498 
2500 {
2501  return GImGui->IO.MousePos;
2502 }
2503 
2505 {
2506  ImGuiWindow* window = GetCurrentWindow();
2507  return window->DC.LastItemHovered;
2508 }
2509 
2511 {
2512  ImGuiState& g = *GImGui;
2513  if (g.ActiveId)
2514  {
2515  ImGuiWindow* window = GetCurrentWindow();
2516  return g.ActiveId == window->DC.LastItemID;
2517  }
2518  return false;
2519 }
2520 
2522 {
2523  ImGuiState& g = *GImGui;
2524  return g.ActiveId != 0;
2525 }
2526 
2528 {
2529  ImGuiWindow* window = GetCurrentWindow();
2530  return window->DC.LastItemAabb.Min;
2531 }
2532 
2534 {
2535  ImGuiWindow* window = GetCurrentWindow();
2536  return window->DC.LastItemAabb.Max;
2537 }
2538 
2539 // Tooltip is stored and turned into a BeginTooltip()/EndTooltip() sequence at the end of the frame. Each call override previous value.
2540 void ImGui::SetTooltipV(const char* fmt, va_list args)
2541 {
2542  ImGuiState& g = *GImGui;
2543  ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args);
2544 }
2545 
2546 void ImGui::SetTooltip(const char* fmt, ...)
2547 {
2548  va_list args;
2549  va_start(args, fmt);
2550  SetTooltipV(fmt, args);
2551  va_end(args);
2552 }
2553 
2555 {
2556  return GImGui->Time;
2557 }
2558 
2560 {
2561  return GImGui->FrameCount;
2562 }
2563 
2565 {
2566  ImGuiState& g = *GImGui;
2568  ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, window_flags);
2569 }
2570 
2572 {
2574  ImGui::End();
2575 }
2576 
2577 bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
2578 {
2579  ImGuiState& g = *GImGui;
2580  ImGuiWindow* window = GetCurrentWindow();
2581 
2583 
2584  const ImVec2 content_max = window->Pos + ImGui::GetContentRegionMax();
2585  const ImVec2 cursor_pos = window->Pos + ImGui::GetCursorPos();
2586  ImVec2 size = size_arg;
2587  if (size.x <= 0.0f)
2588  {
2589  if (size.x == 0.0f)
2591  size.x = ImMax(content_max.x - cursor_pos.x, g.Style.WindowMinSize.x) - fabsf(size.x);
2592  }
2593  if (size.y <= 0.0f)
2594  {
2595  if (size.y == 0.0f)
2597  size.y = ImMax(content_max.y - cursor_pos.y, g.Style.WindowMinSize.y) - fabsf(size.y);
2598  }
2599  if (border)
2601  flags |= extra_flags;
2602 
2603  char title[256];
2604  ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id);
2605 
2606  const float alpha = 1.0f;
2607  bool ret = ImGui::Begin(title, NULL, size, alpha, flags);
2608 
2609  if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
2610  g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders;
2611 
2612  return ret;
2613 }
2614 
2615 bool ImGui::BeginChild(ImGuiID id, const ImVec2& size, bool border, ImGuiWindowFlags extra_flags)
2616 {
2617  char str_id[32];
2618  ImFormatString(str_id, IM_ARRAYSIZE(str_id), "child_%x", id);
2619  bool ret = ImGui::BeginChild(str_id, size, border, extra_flags);
2620  return ret;
2621 }
2622 
2624 {
2625  ImGuiWindow* window = GetCurrentWindow();
2626 
2627  IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
2628  if (window->Flags & ImGuiWindowFlags_ComboBox)
2629  {
2630  ImGui::End();
2631  }
2632  else
2633  {
2634  // When using auto-filling child window, we don't provide the width/height to ItemSize so that it doesn't feed back into automatic size-fitting.
2636  if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX)
2637  sz.x = 0;
2638  if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY)
2639  sz.y = 0;
2640 
2641  ImGui::End();
2642 
2643  window = GetCurrentWindow();
2644  ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + sz);
2645  ItemSize(sz);
2646  ItemAdd(bb, NULL);
2647  }
2648 }
2649 
2650 // Helper to create a child window / scrolling region that looks like a normal widget frame.
2652 {
2653  ImGuiState& g = *GImGui;
2654  const ImGuiStyle& style = g.Style;
2657  ImGui::BeginChild(id, size);
2658 }
2659 
2661 {
2662  ImGui::EndChild();
2665 }
2666 
2667 static ImGuiWindow* FindWindowByName(const char* name)
2668 {
2669  // FIXME-OPT: Store sorted hashes -> pointers.
2670  ImGuiState& g = *GImGui;
2671  ImGuiID id = ImHash(name, 0);
2672  for (size_t i = 0; i < g.Windows.size(); i++)
2673  if (g.Windows[i]->ID == id)
2674  return g.Windows[i];
2675  return NULL;
2676 }
2677 
2678 static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
2679 {
2680  ImGuiState& g = *GImGui;
2681 
2682  // Create window the first time
2683  ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));
2684  new(window) ImGuiWindow(name);
2685  window->Flags = flags;
2686 
2688  {
2689  // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
2690  window->Size = window->SizeFull = size;
2691  }
2692  else
2693  {
2694  // Retrieve settings from .ini file
2695  // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
2696  window->PosFloat = ImVec2(60, 60);
2697  window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
2698 
2699  ImGuiIniData* settings = FindWindowSettings(name);
2700  if (!settings)
2701  {
2702  settings = AddWindowSettings(name);
2703  }
2704  else
2705  {
2706  window->SetWindowPosAllowFlags &= ~ImGuiSetCond_FirstUseEver;
2707  window->SetWindowSizeAllowFlags &= ~ImGuiSetCond_FirstUseEver;
2708  window->SetWindowCollapsedAllowFlags &= ~ImGuiSetCond_FirstUseEver;
2709  }
2710 
2711  if (settings->Pos.x != FLT_MAX)
2712  {
2713  window->PosFloat = settings->Pos;
2714  window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
2715  window->Collapsed = settings->Collapsed;
2716  }
2717 
2718  if (ImLengthSqr(settings->Size) > 0.00001f && !(flags & ImGuiWindowFlags_NoResize))
2719  size = settings->Size;
2720  window->Size = window->SizeFull = size;
2721  }
2722  g.Windows.push_back(window);
2723  return window;
2724 }
2725 
2726 // Push a new ImGui window to add widgets to.
2727 // - 'size' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation.
2728 // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
2729 // - Begin/End can be called multiple times during the frame with the same window name to append content.
2730 // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
2731 // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file.
2732 // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.
2733 // - Passing 'bool* p_opened' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.
2734 // - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiSetCond_FirstUseEver) prior to calling Begin().
2735 bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg_alpha, ImGuiWindowFlags flags)
2736 {
2737  ImGuiState& g = *GImGui;
2738  const ImGuiStyle& style = g.Style;
2739  IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
2740  IM_ASSERT(name != NULL); // Must pass a name
2741 
2742  // Find or create
2743  ImGuiWindow* window = FindWindowByName(name);
2744  if (!window)
2745  window = CreateNewWindow(name, size, flags);
2746  window->Flags = (ImGuiWindowFlags)flags;
2747 
2748  // Add to stack
2749  g.CurrentWindowStack.push_back(window);
2750  g.CurrentWindow = window;
2751 
2752  // Process SetNextWindow***() calls
2753  bool window_pos_set_by_api = false;
2754  if (g.SetNextWindowPosCond)
2755  {
2756  const ImVec2 backup_cursor_pos = window->DC.CursorPos;
2757  ImGui::SetWindowPos(g.SetNextWindowPosVal, g.SetNextWindowPosCond);
2758  window->DC.CursorPos = backup_cursor_pos;
2759  window_pos_set_by_api = true;
2760  g.SetNextWindowPosCond = 0;
2761  }
2762  if (g.SetNextWindowSizeCond)
2763  {
2764  ImGui::SetWindowSize(g.SetNextWindowSizeVal, g.SetNextWindowSizeCond);
2765  g.SetNextWindowSizeCond = 0;
2766  }
2767  if (g.SetNextWindowCollapsedCond)
2768  {
2769  ImGui::SetWindowCollapsed(g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond);
2770  g.SetNextWindowCollapsedCond = 0;
2771  }
2772  if (g.SetNextWindowFocus)
2773  {
2775  g.SetNextWindowFocus = false;
2776  }
2777 
2778  // Find parent
2779  ImGuiWindow* parent_window = (flags & ImGuiWindowFlags_ChildWindow) != 0 ? g.CurrentWindowStack[g.CurrentWindowStack.size()-2] : NULL;
2780 
2781  // Update known root window (if we are a child window, otherwise window == window->RootWindow)
2782  size_t root_idx = g.CurrentWindowStack.size() - 1;
2783  while (root_idx > 0)
2784  {
2785  if ((g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow) == 0)
2786  break;
2787  root_idx--;
2788  }
2789  window->RootWindow = g.CurrentWindowStack[root_idx];
2790 
2791  // Default alpha
2792  if (bg_alpha < 0.0f)
2793  bg_alpha = style.WindowFillAlphaDefault;
2794 
2795  // When reusing window again multiple times a frame, just append content (don't need to setup again)
2796  const int current_frame = ImGui::GetFrameCount();
2797  const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame);
2798  if (first_begin_of_the_frame)
2799  {
2800  window->DrawList->Clear();
2801  window->Visible = true;
2802 
2803  // New windows appears in front
2804  if (window->LastFrameDrawn < current_frame - 1)
2805  FocusWindow(window);
2806 
2807  window->LastFrameDrawn = current_frame;
2808  window->ClipRectStack.resize(0);
2809 
2810  // Reset contents size for auto-fitting
2811  window->SizeContents = window->SizeContentsCurrent;
2812  window->SizeContentsCurrent = ImVec2(0.0f, 0.0f);
2813 
2814  if (flags & ImGuiWindowFlags_ChildWindow)
2815  {
2816  parent_window->DC.ChildWindows.push_back(window);
2817  window->Pos = window->PosFloat = parent_window->DC.CursorPos;
2818  window->SizeFull = size;
2819  }
2820  }
2821 
2822  // Setup texture
2823  window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
2824 
2825  // Setup outer clipping rectangle
2826  if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
2827  PushClipRect(parent_window->ClipRectStack.back());
2828  else if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
2829  PushClipRect(ImVec4(g.IO.DisplayVisibleMin.x, g.IO.DisplayVisibleMin.y, g.IO.DisplayVisibleMax.x, g.IO.DisplayVisibleMax.y));
2830  else
2831  PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
2832 
2833  // Setup and draw window
2834  if (first_begin_of_the_frame)
2835  {
2836  // Reset ID stack
2837  window->IDStack.resize(1);
2838 
2839  // Move window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.
2840  const ImGuiID move_id = window->GetID("#MOVE");
2841  RegisterAliveId(move_id);
2842  if (g.ActiveId == move_id)
2843  {
2844  if (g.IO.MouseDown[0])
2845  {
2846  if (!(window->Flags & ImGuiWindowFlags_NoMove))
2847  {
2848  window->PosFloat += g.IO.MouseDelta;
2849  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
2851  }
2852  IM_ASSERT(g.MovedWindow != NULL);
2853  FocusWindow(g.MovedWindow);
2854  }
2855  else
2856  {
2857  SetActiveId(0);
2858  g.MovedWindow = NULL; // Not strictly necessary but doing it for sanity.
2859  }
2860  }
2861 
2862  // Tooltips always follows mouse
2863  if (!window_pos_set_by_api && (window->Flags & ImGuiWindowFlags_Tooltip) != 0)
2864  {
2865  window->PosFloat = g.IO.MousePos + ImVec2(32,16) - style.FramePadding*2;
2866  }
2867 
2868  // Clamp into view
2869  if (!(window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Tooltip))
2870  {
2871  // FIXME: Parameterize padding.
2872  const ImVec2 pad = ImVec2(window->FontSize()*2.0f, window->FontSize()*2.0f); // FIXME: Parametrize of clarify this behavior.
2873  if (g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
2874  {
2875  ImVec2 clip_min = pad;
2876  ImVec2 clip_max = g.IO.DisplaySize - pad;
2877  window->PosFloat = ImMax(window->PosFloat + window->Size, clip_min) - window->Size;
2878  window->PosFloat = ImMin(window->PosFloat, clip_max);
2879  }
2880  window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize);
2881  }
2882  window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
2883 
2884  // Default item width. Make it proportional to window size if window manually resizes
2885  if (window->Size.x > 0.0f && !(window->Flags & ImGuiWindowFlags_Tooltip) && !(window->Flags & ImGuiWindowFlags_AlwaysAutoResize))
2886  window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
2887  else
2888  window->ItemWidthDefault = 200.0f;
2889 
2890  // Prepare for focus requests
2891  if (window->FocusIdxAllRequestNext == IM_INT_MAX || window->FocusIdxAllCounter == -1)
2892  window->FocusIdxAllRequestCurrent = IM_INT_MAX;
2893  else
2894  window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
2895  if (window->FocusIdxTabRequestNext == IM_INT_MAX || window->FocusIdxTabCounter == -1)
2896  window->FocusIdxTabRequestCurrent = IM_INT_MAX;
2897  else
2898  window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
2899  window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
2900  window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX;
2901 
2902  ImGuiAabb title_bar_aabb = window->TitleBarAabb();
2903 
2904  // Apply and ImClamp scrolling
2905  window->ScrollY = window->NextScrollY;
2906  window->ScrollY = ImMax(window->ScrollY, 0.0f);
2907  if (!window->Collapsed && !window->SkipItems)
2908  window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, window->SizeContents.y - window->SizeFull.y));
2909  window->NextScrollY = window->ScrollY;
2910 
2911  // At this point we don't have a clipping rectangle setup yet, so we can test and draw in title bar
2912  // Collapse window by double-clicking on title bar
2913  if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
2914  {
2915  if (!(window->Flags & ImGuiWindowFlags_NoCollapse) && g.HoveredWindow == window && IsMouseHoveringBox(title_bar_aabb) && g.IO.MouseDoubleClicked[0])
2916  {
2917  window->Collapsed = !window->Collapsed;
2918  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
2920  FocusWindow(window);
2921  }
2922  }
2923  else
2924  {
2925  window->Collapsed = false;
2926  }
2927 
2928  const float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
2929  if (window->Collapsed)
2930  {
2931  // Draw title bar only
2932  window->Size = title_bar_aabb.GetSize();
2933  window->DrawList->AddRectFilled(title_bar_aabb.GetTL(), title_bar_aabb.GetBR(), window->Color(ImGuiCol_TitleBgCollapsed), window_rounding);
2934  if (window->Flags & ImGuiWindowFlags_ShowBorders)
2935  {
2936  window->DrawList->AddRect(title_bar_aabb.GetTL()+ImVec2(1,1), title_bar_aabb.GetBR()+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
2937  window->DrawList->AddRect(title_bar_aabb.GetTL(), title_bar_aabb.GetBR(), window->Color(ImGuiCol_Border), window_rounding);
2938  }
2939  }
2940  else
2941  {
2942  window->Size = window->SizeFull;
2943 
2944  ImU32 resize_col = 0;
2945  if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
2946  {
2947  // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
2948  const ImVec2 size_auto_fit = window->SizeContents + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);
2949  window->SizeFull = size_auto_fit;
2950  }
2951  else
2952  {
2953  const ImVec2 size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding));
2954  if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
2955  {
2956  // Don't continuously mark settings as dirty, the size of the window doesn't need to be stored.
2957  window->SizeFull = size_auto_fit;
2958  }
2959  else if (window->AutoFitFrames > 0)
2960  {
2961  // Auto-fit only grows during the first few frames
2962  if (window->AutoFitOnlyGrows)
2963  window->SizeFull = ImMax(window->SizeFull, size_auto_fit);
2964  else
2965  window->SizeFull = size_auto_fit;
2966  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
2968  }
2969  else if (!(window->Flags & ImGuiWindowFlags_NoResize))
2970  {
2971  // Manual resize grip
2972  const ImGuiAabb resize_aabb(window->Aabb().GetBR()-ImVec2(18,18), window->Aabb().GetBR());
2973  const ImGuiID resize_id = window->GetID("#RESIZE");
2974  bool hovered, held;
2975  ButtonBehaviour(resize_aabb, resize_id, &hovered, &held, true);
2976  resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
2977 
2978  if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
2979  {
2980  // Manual auto-fit when double-clicking
2981  window->SizeFull = size_auto_fit;
2982  window->Size = window->SizeFull;
2983  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
2985  }
2986  else if (held)
2987  {
2988  // Resize
2989  window->SizeFull = ImMax(window->SizeFull + g.IO.MouseDelta, style.WindowMinSize);
2990  window->Size = window->SizeFull;
2991  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
2993  }
2994  }
2995 
2996  // Update aabb immediately so that rendering right below us isn't one frame late
2997  title_bar_aabb = window->TitleBarAabb();
2998  }
2999 
3000  // Scrollbar
3001  window->ScrollbarY = (window->SizeContents.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar);
3002 
3003  // Window background
3004  if (bg_alpha > 0.0f)
3005  {
3006  if ((window->Flags & ImGuiWindowFlags_ComboBox) != 0)
3007  window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_ComboBg, bg_alpha), window_rounding);
3008  else if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
3009  window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_TooltipBg, bg_alpha), window_rounding);
3010  else if ((window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
3011  window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size-ImVec2(window->ScrollbarY?style.ScrollbarWidth:0.0f,0.0f), window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
3012  else
3013  window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
3014  }
3015 
3016  // Title bar
3017  if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
3018  window->DrawList->AddRectFilled(title_bar_aabb.GetTL(), title_bar_aabb.GetBR(), window->Color(ImGuiCol_TitleBg), window_rounding, 1|2);
3019 
3020  // Borders
3021  if (window->Flags & ImGuiWindowFlags_ShowBorders)
3022  {
3023  window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
3024  window->DrawList->AddRect(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_Border), window_rounding);
3025  if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
3026  window->DrawList->AddLine(title_bar_aabb.GetBL(), title_bar_aabb.GetBR(), window->Color(ImGuiCol_Border));
3027  }
3028 
3029  // Scrollbar
3030  if (window->ScrollbarY)
3031  Scrollbar(window);
3032 
3033  // Render resize grip
3034  // (after the input handling so we don't have a frame of latency)
3035  if (!(window->Flags & ImGuiWindowFlags_NoResize))
3036  {
3037  const float r = window_rounding;
3038  const ImVec2 br = window->Aabb().GetBR();
3039  if (r == 0.0f)
3040  {
3041  window->DrawList->AddTriangleFilled(br, br-ImVec2(0,14), br-ImVec2(14,0), resize_col);
3042  }
3043  else
3044  {
3045  // FIXME: We should draw 4 triangles and decide on a size that's not dependent on the rounding size (previously used 18)
3046  window->DrawList->AddArc(br - ImVec2(r,r), r, resize_col, 6, 9, true);
3047  window->DrawList->AddTriangleFilled(br+ImVec2(0,-2*r),br+ImVec2(0,-r),br+ImVec2(-r,-r), resize_col);
3048  window->DrawList->AddTriangleFilled(br+ImVec2(-r,-r), br+ImVec2(-r,0),br+ImVec2(-2*r,0), resize_col);
3049  }
3050  }
3051  }
3052 
3053  // Setup drawing context
3054  window->DC.ColumnsStartX = window->WindowPadding().x;
3055  window->DC.ColumnsOffsetX = 0.0f;
3056  window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.ColumnsStartX + window->DC.ColumnsOffsetX, window->TitleBarHeight() + window->WindowPadding().y) - ImVec2(0.0f, window->ScrollY);
3057  window->DC.CursorPos = window->DC.CursorStartPos;
3058  window->DC.CursorPosPrevLine = window->DC.CursorPos;
3059  window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f;
3060  window->DC.LogLineHeight = window->DC.CursorPos.y - 9999.0f;
3061  window->DC.ChildWindows.resize(0);
3062  window->DC.ItemWidth.resize(0);
3063  window->DC.ItemWidth.push_back(window->ItemWidthDefault);
3064  window->DC.AllowKeyboardFocus.resize(0);
3065  window->DC.AllowKeyboardFocus.push_back(true);
3066  window->DC.TextWrapPos.resize(0);
3067  window->DC.TextWrapPos.push_back(-1.0f); // disabled
3068  window->DC.ColorEditMode = ImGuiColorEditMode_UserSelect;
3069  window->DC.ColumnsCurrent = 0;
3070  window->DC.ColumnsCount = 1;
3071  window->DC.ColumnsStartPos = window->DC.CursorPos;
3072  window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPos.y;
3073  window->DC.TreeDepth = 0;
3074  window->DC.StateStorage = &window->StateStorage;
3075 
3076  if (window->AutoFitFrames > 0)
3077  window->AutoFitFrames--;
3078 
3079  // Title bar
3080  if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
3081  {
3082  if (p_opened != NULL)
3083  CloseWindowButton(p_opened);
3084 
3085  ImVec2 text_min = window->Pos + style.FramePadding;
3086  if (!(window->Flags & ImGuiWindowFlags_NoCollapse))
3087  {
3088  RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
3089  text_min.x += window->FontSize() + style.ItemInnerSpacing.x;
3090  }
3091 
3092  const ImVec2 text_size = CalcTextSize(name, NULL, true);
3093  const ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? (title_bar_aabb.GetHeight()-3) : style.FramePadding.x), style.FramePadding.y*2 + text_size.y);
3094  RenderTextClipped(text_min, name, NULL, &text_size, text_max);
3095  }
3096 
3097  // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
3098  window->ClippedAabb = window->Aabb();
3099  window->ClippedAabb.Clip(window->ClipRectStack.front());
3100  }
3101 
3102  // Inner clipping rectangle
3103  // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
3104  const ImGuiAabb title_bar_aabb = window->TitleBarAabb();
3105  ImVec4 clip_rect(title_bar_aabb.Min.x+0.5f+window->WindowPadding().x*0.5f, title_bar_aabb.Max.y+0.5f, window->Aabb().Max.x+0.5f-window->WindowPadding().x*0.5f, window->Aabb().Max.y-1.5f);
3106  if (window->ScrollbarY)
3107  clip_rect.z -= style.ScrollbarWidth;
3108  PushClipRect(clip_rect);
3109 
3110  // Clear 'accessed' flag last thing
3111  if (first_begin_of_the_frame)
3112  window->Accessed = false;
3113 
3114  // Child window can be out of sight and have "negative" clip windows.
3115  // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar).
3116  if (flags & ImGuiWindowFlags_ChildWindow)
3117  {
3118  IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);
3119  window->Collapsed = parent_window && parent_window->Collapsed;
3120 
3121  const ImVec4 clip_rect_t = window->ClipRectStack.back();
3122  window->Collapsed |= (clip_rect_t.x >= clip_rect_t.z || clip_rect_t.y >= clip_rect_t.w);
3123 
3124  // We also hide the window from rendering because we've already added its border to the command list.
3125  // (we could perform the check earlier in the function but it is simpler at this point)
3126  if (window->Collapsed)
3127  window->Visible = false;
3128  }
3129  if (style.Alpha <= 0.0f)
3130  window->Visible = false;
3131 
3132  // Return false if we don't intend to display anything to allow user to perform an early out optimization
3133  window->SkipItems = window->Collapsed || (!window->Visible && window->AutoFitFrames == 0);
3134  return !window->SkipItems;
3135 }
3136 
3138 {
3139  ImGuiState& g = *GImGui;
3140  ImGuiWindow* window = g.CurrentWindow;
3141 
3142  ImGui::Columns(1, "#CloseColumns");
3143  PopClipRect(); // inner window clip rectangle
3144  PopClipRect(); // outer window clip rectangle
3145  window->DrawList->PopTextureID();
3146 
3147  // Stop logging
3148  if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
3149  ImGui::LogFinish();
3150 
3151  // Pop
3152  // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin().
3153  g.CurrentWindowStack.pop_back();
3154  g.CurrentWindow = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
3155 }
3156 
3157 // Vertical scrollbar
3158 // The entire piece of code below is rather confusing because:
3159 // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
3160 // - We store values as ratio and in a form that allows the window content to change while we are holding on a scrollbar
3161 static void Scrollbar(ImGuiWindow* window)
3162 {
3163  ImGuiState& g = *GImGui;
3164  const ImGuiStyle& style = g.Style;
3165  const ImGuiID id = window->GetID("#SCROLLY");
3166 
3167  // Render background
3168  ImGuiAabb bb(window->Aabb().Max.x - style.ScrollbarWidth, window->Pos.y + window->TitleBarHeight()+1, window->Aabb().Max.x, window->Aabb().Max.y-1);
3169  window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg));
3170  bb.Expand(ImVec2(-3,-3));
3171  const float scrollbar_height = bb.GetHeight();
3172 
3173  // The grabable box size generally represent the amount visible (vs the total scrollable amount)
3174  // But we maintain a minimum size in pixel to allow for the user to still aim inside.
3175  const float grab_h_pixels = ImMax(style.GrabMinSize, scrollbar_height * ImSaturate(window->Size.y / ImMax(window->SizeContents.y, window->Size.y)));
3176  const float grab_h_norm = grab_h_pixels / scrollbar_height;
3177 
3178  // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
3179  bool held = false;
3180  bool hovered = false;
3181  const bool previously_held = (g.ActiveId == id);
3182  ButtonBehaviour(bb, id, &hovered, &held, true);
3183 
3184  const float scroll_max = ImMax(1.0f, window->SizeContents.y - window->Size.y);
3185  float scroll_ratio = ImSaturate(window->ScrollY / scroll_max);
3186  float grab_y_norm = scroll_ratio * (scrollbar_height - grab_h_pixels) / scrollbar_height;
3187  if (held)
3188  {
3189  const float clicked_y_norm = ImSaturate((g.IO.MousePos.y - bb.Min.y) / scrollbar_height); // Click position in scrollbar space (0.0f->1.0f)
3190  g.HoveredId = id;
3191 
3192  bool seek_absolute = false;
3193  if (!previously_held)
3194  {
3195  // On initial click calculate the distance between mouse and the center of the grab
3196  if (clicked_y_norm >= grab_y_norm && clicked_y_norm <= grab_y_norm + grab_h_norm)
3197  {
3198  g.ScrollbarClickDeltaToGrabCenter = clicked_y_norm - grab_y_norm - grab_h_norm*0.5f;
3199  }
3200  else
3201  {
3202  seek_absolute = true;
3203  g.ScrollbarClickDeltaToGrabCenter = 0;
3204  }
3205  }
3206 
3207  // Apply scroll
3208  const float scroll_y_norm = ImSaturate((clicked_y_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm*0.5f) / (1.0f - grab_h_norm));
3209  window->ScrollY = (float)(int)(0.5f + scroll_y_norm * (window->SizeContents.y - window->Size.y));
3210  window->NextScrollY = window->ScrollY;
3211 
3212  // Update values for rendering
3213  scroll_ratio = ImSaturate(window->ScrollY / scroll_max);
3214  grab_y_norm = scroll_ratio * (scrollbar_height - grab_h_pixels) / scrollbar_height;
3215 
3216  // Update distance to grab now that we have seeked and saturated
3217  if (seek_absolute)
3218  g.ScrollbarClickDeltaToGrabCenter = clicked_y_norm - grab_y_norm - grab_h_norm*0.5f;
3219  }
3220 
3221  // Render
3222  const ImU32 grab_col = window->Color(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);
3223  window->DrawList->AddRectFilled(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm)), ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_y_norm) + grab_h_pixels), grab_col);
3224 }
3225 
3226 // Moving window to front of display (which happens to be back of our sorted list)
3227 static void FocusWindow(ImGuiWindow* window)
3228 {
3229  ImGuiState& g = *GImGui;
3230 
3231  // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing.
3232  g.FocusedWindow = window;
3233 
3234  // And move its root window to the top of the pile
3235  if (window->RootWindow)
3236  window = window->RootWindow;
3237 
3238  if (g.Windows.back() == window)
3239  return;
3240 
3241  for (size_t i = 0; i < g.Windows.size(); i++)
3242  if (g.Windows[i] == window)
3243  {
3244  g.Windows.erase(g.Windows.begin() + i);
3245  break;
3246  }
3247  g.Windows.push_back(window);
3248 }
3249 
3250 void ImGui::PushItemWidth(float item_width)
3251 {
3252  ImGuiWindow* window = GetCurrentWindow();
3253  window->DC.ItemWidth.push_back(item_width == 0.0f ? window->ItemWidthDefault : item_width);
3254 }
3255 
3257 {
3258  ImGuiWindow* window = GetCurrentWindow();
3259  window->DC.ItemWidth.pop_back();
3260 }
3261 
3263 {
3264  ImGuiWindow* window = GetCurrentWindow();
3265  float w = window->DC.ItemWidth.back();
3266  if (w < 0.0f)
3267  {
3268  // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well.
3269  ImGuiState& g = *GImGui;
3270  w = -w;
3271  float width_to_right_edge = window->Pos.x + ImGui::GetContentRegionMax().x - window->DC.CursorPos.x;
3272  w = ImMax(1.0f, width_to_right_edge - w - g.Style.FramePadding.x * 2.0f);
3273  }
3274  w = (float)(int)w;
3275  return w;
3276 }
3277 
3278 static void SetFont(ImFont* font)
3279 {
3280  ImGuiState& g = *GImGui;
3281 
3282  IM_ASSERT(font && font->IsLoaded());
3283  IM_ASSERT(font->Scale > 0.0f);
3284  g.Font = font;
3285  g.FontSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
3286  g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel;
3287 }
3288 
3290 {
3291  ImGuiState& g = *GImGui;
3292 
3293  if (!font)
3294  font = g.IO.Fonts->Fonts[0];
3295 
3296  SetFont(font);
3297  g.FontStack.push_back(font);
3298  g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
3299 }
3300 
3302 {
3303  ImGuiState& g = *GImGui;
3304 
3305  g.CurrentWindow->DrawList->PopTextureID();
3306  g.FontStack.pop_back();
3307  SetFont(g.FontStack.empty() ? g.IO.Fonts->Fonts[0] : g.FontStack.back());
3308 }
3309 
3310 void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
3311 {
3312  ImGuiWindow* window = GetCurrentWindow();
3313  window->DC.AllowKeyboardFocus.push_back(allow_keyboard_focus);
3314 }
3315 
3317 {
3318  ImGuiWindow* window = GetCurrentWindow();
3319  window->DC.AllowKeyboardFocus.pop_back();
3320 }
3321 
3322 void ImGui::PushTextWrapPos(float wrap_x)
3323 {
3324  ImGuiWindow* window = GetCurrentWindow();
3325  window->DC.TextWrapPos.push_back(wrap_x);
3326 }
3327 
3329 {
3330  ImGuiWindow* window = GetCurrentWindow();
3331  window->DC.TextWrapPos.pop_back();
3332 }
3333 
3335 {
3336  ImGuiState& g = *GImGui;
3337 
3338  ImGuiColMod backup;
3339  backup.Col = idx;
3340  backup.PreviousValue = g.Style.Colors[idx];
3341  g.ColorModifiers.push_back(backup);
3342  g.Style.Colors[idx] = col;
3343 }
3344 
3345 void ImGui::PopStyleColor(int count)
3346 {
3347  ImGuiState& g = *GImGui;
3348 
3349  while (count > 0)
3350  {
3351  ImGuiColMod& backup = g.ColorModifiers.back();
3352  g.Style.Colors[backup.Col] = backup.PreviousValue;
3353  g.ColorModifiers.pop_back();
3354  count--;
3355  }
3356 }
3357 
3359 {
3360  ImGuiState& g = *GImGui;
3361  switch (idx)
3362  {
3363  case ImGuiStyleVar_Alpha: return &g.Style.Alpha;
3364  case ImGuiStyleVar_WindowRounding: return &g.Style.WindowRounding;
3365  case ImGuiStyleVar_ChildWindowRounding: return &g.Style.ChildWindowRounding;
3366  case ImGuiStyleVar_FrameRounding: return &g.Style.FrameRounding;
3367  case ImGuiStyleVar_TreeNodeSpacing: return &g.Style.TreeNodeSpacing;
3368  }
3369  return NULL;
3370 }
3371 
3373 {
3374  ImGuiState& g = *GImGui;
3375  switch (idx)
3376  {
3377  case ImGuiStyleVar_WindowPadding: return &g.Style.WindowPadding;
3378  case ImGuiStyleVar_FramePadding: return &g.Style.FramePadding;
3379  case ImGuiStyleVar_ItemSpacing: return &g.Style.ItemSpacing;
3380  case ImGuiStyleVar_ItemInnerSpacing: return &g.Style.ItemInnerSpacing;
3381  }
3382  return NULL;
3383 }
3384 
3386 {
3387  ImGuiState& g = *GImGui;
3388 
3389  float* pvar = GetStyleVarFloatAddr(idx);
3390  IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a float.
3391  ImGuiStyleMod backup;
3392  backup.Var = idx;
3393  backup.PreviousValue = ImVec2(*pvar, 0.0f);
3394  g.StyleModifiers.push_back(backup);
3395  *pvar = val;
3396 }
3397 
3398 
3400 {
3401  ImGuiState& g = *GImGui;
3402 
3403  ImVec2* pvar = GetStyleVarVec2Addr(idx);
3404  IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a ImVec2.
3405  ImGuiStyleMod backup;
3406  backup.Var = idx;
3407  backup.PreviousValue = *pvar;
3408  g.StyleModifiers.push_back(backup);
3409  *pvar = val;
3410 }
3411 
3412 void ImGui::PopStyleVar(int count)
3413 {
3414  ImGuiState& g = *GImGui;
3415 
3416  while (count > 0)
3417  {
3418  ImGuiStyleMod& backup = g.StyleModifiers.back();
3419  if (float* pvar_f = GetStyleVarFloatAddr(backup.Var))
3420  *pvar_f = backup.PreviousValue.x;
3421  else if (ImVec2* pvar_v = GetStyleVarVec2Addr(backup.Var))
3422  *pvar_v = backup.PreviousValue;
3423  g.StyleModifiers.pop_back();
3424  count--;
3425  }
3426 }
3427 
3429 {
3430  // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
3431  switch (idx)
3432  {
3433  case ImGuiCol_Text: return "Text";
3434  case ImGuiCol_WindowBg: return "WindowBg";
3435  case ImGuiCol_ChildWindowBg: return "ChildWindowBg";
3436  case ImGuiCol_Border: return "Border";
3437  case ImGuiCol_BorderShadow: return "BorderShadow";
3438  case ImGuiCol_FrameBg: return "FrameBg";
3439  case ImGuiCol_TitleBg: return "TitleBg";
3440  case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
3441  case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
3442  case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
3443  case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
3444  case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
3445  case ImGuiCol_ComboBg: return "ComboBg";
3446  case ImGuiCol_CheckHovered: return "CheckHovered";
3447  case ImGuiCol_CheckActive: return "CheckActive";
3448  case ImGuiCol_CheckMark: return "CheckMark";
3449  case ImGuiCol_SliderGrab: return "SliderGrab";
3450  case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
3451  case ImGuiCol_Button: return "Button";
3452  case ImGuiCol_ButtonHovered: return "ButtonHovered";
3453  case ImGuiCol_ButtonActive: return "ButtonActive";
3454  case ImGuiCol_Header: return "Header";
3455  case ImGuiCol_HeaderHovered: return "HeaderHovered";
3456  case ImGuiCol_HeaderActive: return "HeaderActive";
3457  case ImGuiCol_Column: return "Column";
3458  case ImGuiCol_ColumnHovered: return "ColumnHovered";
3459  case ImGuiCol_ColumnActive: return "ColumnActive";
3460  case ImGuiCol_ResizeGrip: return "ResizeGrip";
3461  case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
3462  case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
3463  case ImGuiCol_CloseButton: return "CloseButton";
3464  case ImGuiCol_CloseButtonHovered: return "CloseButtonHovered";
3465  case ImGuiCol_CloseButtonActive: return "CloseButtonActive";
3466  case ImGuiCol_PlotLines: return "PlotLines";
3467  case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
3468  case ImGuiCol_PlotHistogram: return "PlotHistogram";
3469  case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
3470  case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
3471  case ImGuiCol_TooltipBg: return "TooltipBg";
3472  }
3473  IM_ASSERT(0);
3474  return "Unknown";
3475 }
3476 
3478 {
3479  ImGuiState& g = *GImGui;
3480  ImGuiWindow* window = GetCurrentWindow();
3481  return g.FocusedWindow == window;
3482 }
3483 
3485 {
3486  ImGuiWindow* window = GetCurrentWindow();
3487  return window->Size.x;
3488 }
3489 
3491 {
3492  ImGuiWindow* window = GetCurrentWindow();
3493  return window->Pos;
3494 }
3495 
3496 static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond)
3497 {
3498  // Test condition (NB: bit 0 is always true) and clear flags for next time
3499  if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
3500  return;
3501  window->SetWindowPosAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver);
3502 
3503  // Set
3504  const ImVec2 old_pos = window->Pos;
3505  window->PosFloat = pos;
3506  window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
3507  window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
3508 }
3509 
3511 {
3512  ImGuiWindow* window = GetCurrentWindow();
3513  SetWindowPos(window, pos, cond);
3514 }
3515 
3516 void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiSetCond cond)
3517 {
3518  ImGuiWindow* window = FindWindowByName(name);
3519  if (window)
3520  SetWindowPos(window, pos, cond);
3521 }
3522 
3524 {
3525  ImGuiWindow* window = GetCurrentWindow();
3526  return window->Size;
3527 }
3528 
3529 static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond)
3530 {
3531  // Test condition (NB: bit 0 is always true) and clear flags for next time
3532  if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
3533  return;
3534  window->SetWindowSizeAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver);
3535 
3536  // Set
3537  if (ImLengthSqr(size) > 0.00001f)
3538  {
3539  window->SizeFull = size;
3540  window->AutoFitFrames = 0;
3541  }
3542  else
3543  {
3544  // Autofit
3545  window->AutoFitFrames = 2;
3546  window->AutoFitOnlyGrows = false;
3547  }
3548 }
3549 
3551 {
3552  ImGuiWindow* window = GetCurrentWindow();
3553  SetWindowSize(window, size, cond);
3554 }
3555 
3556 void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiSetCond cond)
3557 {
3558  ImGuiWindow* window = FindWindowByName(name);
3559  if (window)
3560  SetWindowSize(window, size, cond);
3561 }
3562 
3563 static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiSetCond cond)
3564 {
3565  // Test condition (NB: bit 0 is always true) and clear flags for next time
3566  if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
3567  return;
3568  window->SetWindowCollapsedAllowFlags &= ~(ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver);
3569 
3570  // Set
3571  window->Collapsed = collapsed;
3572 }
3573 
3574 void ImGui::SetWindowCollapsed(bool collapsed, ImGuiSetCond cond)
3575 {
3576  ImGuiWindow* window = GetCurrentWindow();
3577  SetWindowCollapsed(window, collapsed, cond);
3578 }
3579 
3581 {
3582  ImGuiWindow* window = GetCurrentWindow();
3583  return window->Collapsed;
3584 }
3585 
3586 void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond)
3587 {
3588  ImGuiWindow* window = FindWindowByName(name);
3589  if (window)
3590  SetWindowCollapsed(window, collapsed, cond);
3591 }
3592 
3594 {
3595  ImGuiWindow* window = GetCurrentWindow();
3596  FocusWindow(window);
3597 }
3598 
3599 void ImGui::SetWindowFocus(const char* name)
3600 {
3601  ImGuiWindow* window = FindWindowByName(name);
3602  if (window)
3603  FocusWindow(window);
3604 }
3605 
3607 {
3608  ImGuiState& g = *GImGui;
3609  g.SetNextWindowPosVal = pos;
3610  g.SetNextWindowPosCond = cond ? cond : ImGuiSetCond_Always;
3611 }
3612 
3614 {
3615  ImGuiState& g = *GImGui;
3616  g.SetNextWindowSizeVal = size;
3617  g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always;
3618 }
3619 
3621 {
3622  ImGuiState& g = *GImGui;
3623  g.SetNextWindowCollapsedVal = collapsed;
3624  g.SetNextWindowCollapsedCond = cond ? cond : ImGuiSetCond_Always;
3625 }
3626 
3628 {
3629  ImGuiState& g = *GImGui;
3630  g.SetNextWindowFocus = true;
3631 }
3632 
3634 {
3635  ImGuiWindow* window = GetCurrentWindow();
3636  ImVec2 window_padding = window->WindowPadding();
3637  ImVec2 mx = window->Size - window_padding;
3638  if (window->DC.ColumnsCount != 1)
3639  {
3640  mx.x = ImGui::GetColumnOffset(window->DC.ColumnsCurrent + 1);
3641  mx.x -= window_padding.x;
3642  }
3643  else
3644  {
3645  if (window->ScrollbarY)
3646  mx.x -= GImGui->Style.ScrollbarWidth;
3647  }
3648  return mx;
3649 }
3650 
3652 {
3653  ImGuiWindow* window = GetCurrentWindow();
3654  return ImVec2(0, window->TitleBarHeight()) + window->WindowPadding();
3655 }
3656 
3658 {
3659  ImGuiWindow* window = GetCurrentWindow();
3660  ImVec2 m = window->Size - window->WindowPadding();
3661  if (window->ScrollbarY)
3662  m.x -= GImGui->Style.ScrollbarWidth;
3663  return m;
3664 }
3665 
3667 {
3668  ImGuiWindow* window = GetCurrentWindow();
3669  return window->FontSize();
3670 }
3671 
3673 {
3674  ImGuiState& g = *GImGui;
3675  ImGuiWindow* window = GetCurrentWindow();
3676  return window->FontSize() + g.Style.ItemSpacing.y;
3677 }
3678 
3680 {
3681  ImGuiWindow* window = GetCurrentWindow();
3682  return window->DrawList;
3683 }
3684 
3686 {
3687  ImGuiWindow* window = GetCurrentWindow();
3688  return window->Font();
3689 }
3690 
3692 {
3693  ImGuiWindow* window = GetCurrentWindow();
3694  return window->FontSize();
3695 }
3696 
3698 {
3699  ImGuiWindow* window = GetCurrentWindow();
3700  window->FontWindowScale = scale;
3701 }
3702 
3703 // NB: internally we store CursorPos in absolute screen coordinates because it is more convenient.
3704 // Conversion happens as we pass the value to user, but it makes our naming convention dodgy. May want to rename 'DC.CursorPos'.
3706 {
3707  ImGuiWindow* window = GetCurrentWindow();
3708  return window->DC.CursorPos - window->Pos;
3709 }
3710 
3712 {
3713  return ImGui::GetCursorPos().x;
3714 }
3715 
3717 {
3718  return ImGui::GetCursorPos().y;
3719 }
3720 
3721 void ImGui::SetCursorPos(const ImVec2& pos)
3722 {
3723  ImGuiWindow* window = GetCurrentWindow();
3724  window->DC.CursorPos = window->Pos + pos;
3725  window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, pos + ImVec2(0.0f, window->ScrollY));
3726 }
3727 
3729 {
3730  ImGuiWindow* window = GetCurrentWindow();
3731  window->DC.CursorPos.x = window->Pos.x + x;
3732  window->SizeContentsCurrent.x = ImMax(window->SizeContentsCurrent.x, x);
3733 }
3734 
3736 {
3737  ImGuiWindow* window = GetCurrentWindow();
3738  window->DC.CursorPos.y = window->Pos.y + y;
3739  window->SizeContentsCurrent.y = ImMax(window->SizeContentsCurrent.y, y + window->ScrollY);
3740 }
3741 
3743 {
3744  ImGuiWindow* window = GetCurrentWindow();
3745  return window->DC.CursorPos;
3746 }
3747 
3748 void ImGui::SetCursorScreenPos(const ImVec2& screen_pos)
3749 {
3750  ImGuiWindow* window = GetCurrentWindow();
3751  window->DC.CursorPos = screen_pos;
3752 }
3753 
3755 {
3756  ImGuiWindow* window = GetCurrentWindow();
3757  return window->ScrollY;
3758 }
3759 
3761 {
3762  ImGuiWindow* window = GetCurrentWindow();
3763  return window->SizeContents.y - window->SizeFull.y;
3764 }
3765 
3767 {
3768  ImGuiWindow* window = GetCurrentWindow();
3769  window->NextScrollY = (window->DC.CursorPos.y + window->ScrollY) - (window->Pos.y + window->SizeFull.y * 0.5f) - (window->TitleBarHeight() + window->WindowPadding().y);
3770 }
3771 
3773 {
3774  ImGuiWindow* window = GetCurrentWindow();
3775  window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
3776  window->FocusIdxTabRequestNext = IM_INT_MAX;
3777 }
3778 
3780 {
3781  ImGuiWindow* window = GetCurrentWindow();
3782  window->DC.StateStorage = tree ? tree : &window->StateStorage;
3783 }
3784 
3786 {
3787  ImGuiWindow* window = GetCurrentWindow();
3788  return window->DC.StateStorage;
3789 }
3790 
3791 void ImGui::TextV(const char* fmt, va_list args)
3792 {
3793  ImGuiWindow* window = GetCurrentWindow();
3794  if (window->SkipItems)
3795  return;
3796 
3797  static char buf[1024];
3798  const char* text_end = buf + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
3799  TextUnformatted(buf, text_end);
3800 }
3801 
3802 void ImGui::Text(const char* fmt, ...)
3803 {
3804  va_list args;
3805  va_start(args, fmt);
3806  TextV(fmt, args);
3807  va_end(args);
3808 }
3809 
3810 void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
3811 {
3813  TextV(fmt, args);
3815 }
3816 
3817 void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
3818 {
3819  va_list args;
3820  va_start(args, fmt);
3821  TextColoredV(col, fmt, args);
3822  va_end(args);
3823 }
3824 
3825 void ImGui::TextWrappedV(const char* fmt, va_list args)
3826 {
3827  ImGui::PushTextWrapPos(0.0f);
3828  TextV(fmt, args);
3830 }
3831 
3832 void ImGui::TextWrapped(const char* fmt, ...)
3833 {
3834  va_list args;
3835  va_start(args, fmt);
3836  TextWrappedV(fmt, args);
3837  va_end(args);
3838 }
3839 
3840 void ImGui::TextUnformatted(const char* text, const char* text_end)
3841 {
3842  ImGuiState& g = *GImGui;
3843  ImGuiWindow* window = GetCurrentWindow();
3844  if (window->SkipItems)
3845  return;
3846 
3847  IM_ASSERT(text != NULL);
3848  const char* text_begin = text;
3849  if (text_end == NULL)
3850  text_end = text + strlen(text); // FIXME-OPT
3851 
3852  const float wrap_pos_x = window->DC.TextWrapPos.back();
3853  const bool wrap_enabled = wrap_pos_x >= 0.0f;
3854  if (text_end - text > 2000 && !wrap_enabled)
3855  {
3856  // Long text!
3857  // Perform manual coarse clipping to optimize for long multi-line text
3858  // From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
3859  // We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
3860  const char* line = text;
3861  const float line_height = ImGui::GetTextLineHeight();
3862  const ImVec2 start_pos = window->DC.CursorPos;
3863  const ImVec4 clip_rect = window->ClipRectStack.back();
3864  ImVec2 text_size(0,0);
3865 
3866  if (start_pos.y <= clip_rect.w)
3867  {
3868  ImVec2 pos = start_pos;
3869 
3870  // Lines to skip (can't skip when logging text)
3871  if (!g.LogEnabled)
3872  {
3873  int lines_skippable = (int)((clip_rect.y - start_pos.y) / line_height) - 1;
3874  if (lines_skippable > 0)
3875  {
3876  int lines_skipped = 0;
3877  while (line < text_end && lines_skipped <= lines_skippable)
3878  {
3879  const char* line_end = strchr(line, '\n');
3880  line = line_end + 1;
3881  lines_skipped++;
3882  }
3883  pos.y += lines_skipped * line_height;
3884  }
3885  }
3886 
3887  // Lines to render
3888  if (line < text_end)
3889  {
3890  ImGuiAabb line_box(pos, pos + ImVec2(ImGui::GetWindowWidth(), line_height));
3891  while (line < text_end)
3892  {
3893  const char* line_end = strchr(line, '\n');
3894  if (IsClipped(line_box))
3895  break;
3896 
3897  const ImVec2 line_size = CalcTextSize(line, line_end, false);
3898  text_size.x = ImMax(text_size.x, line_size.x);
3899  RenderText(pos, line, line_end, false);
3900  if (!line_end)
3901  line_end = text_end;
3902  line = line_end + 1;
3903  line_box.Min.y += line_height;
3904  line_box.Max.y += line_height;
3905  pos.y += line_height;
3906  }
3907 
3908  // Count remaining lines
3909  int lines_skipped = 0;
3910  while (line < text_end)
3911  {
3912  const char* line_end = strchr(line, '\n');
3913  if (!line_end)
3914  line_end = text_end;
3915  line = line_end + 1;
3916  lines_skipped++;
3917  }
3918  pos.y += lines_skipped * line_height;
3919  }
3920 
3921  text_size.y += (pos - start_pos).y;
3922  }
3923  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + text_size);
3924  ItemSize(bb);
3925  ItemAdd(bb, NULL);
3926  }
3927  else
3928  {
3929  const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
3930  const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
3931  ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + text_size);
3932  ItemSize(bb.GetSize(), &bb.Min);
3933  if (!ItemAdd(bb, NULL))
3934  return;
3935 
3936  // Render (we don't hide text after ## in this end-user function)
3937  RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
3938  }
3939 }
3940 
3942 {
3943  ImGuiState& g = *GImGui;
3944  ImGuiWindow* window = GetCurrentWindow();
3945  if (window->SkipItems)
3946  return;
3947 
3948  // Declare a dummy item size to that upcoming items that are smaller will center-align on the newly expanded line height.
3949  ItemSize(ImVec2(0, window->FontSize() + g.Style.FramePadding.y*2));
3950  ImGui::SameLine(0, 0);
3951 }
3952 
3953 // Add a label+text combo aligned to other label+value widgets
3954 void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
3955 {
3956  ImGuiState& g = *GImGui;
3957  ImGuiWindow* window = GetCurrentWindow();
3958  if (window->SkipItems)
3959  return;
3960  const ImGuiStyle& style = g.Style;
3961  const float w = ImGui::CalcItemWidth();
3962 
3963  static char buf[1024];
3964  const char* value_text_begin = &buf[0];
3965  const char* value_text_end = value_text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
3966 
3967  const ImVec2 label_size = CalcTextSize(label, NULL, true);
3968  const ImGuiAabb value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2, label_size.y));
3969  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2 + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), 0.0f) + label_size);
3970  ItemSize(bb);
3971  if (!ItemAdd(value_bb, NULL))
3972  return;
3973 
3974  // Render
3975  RenderTextClipped(value_bb.Min, value_text_begin, value_text_end, NULL, value_bb.Max);
3976  RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y), label);
3977 }
3978 
3979 void ImGui::LabelText(const char* label, const char* fmt, ...)
3980 {
3981  va_list args;
3982  va_start(args, fmt);
3983  LabelTextV(label, fmt, args);
3984  va_end(args);
3985 }
3986 
3987 static bool IsHovered(const ImGuiAabb& bb, const ImGuiID& id)
3988 {
3989  ImGuiState& g = *GImGui;
3990  if (g.HoveredId == 0)
3991  {
3992  ImGuiWindow* window = GetCurrentWindow();
3993  if (g.HoveredRootWindow == window->RootWindow)
3994  {
3995  bool hovered = (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && IsMouseHoveringBox(bb);
3996  return hovered;
3997  }
3998  }
3999  return false;
4000 }
4001 
4002 static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click)
4003 {
4004  ImGuiState& g = *GImGui;
4005  ImGuiWindow* window = GetCurrentWindow();
4006 
4007  const bool hovered = IsHovered(bb, id);
4008  bool pressed = false;
4009  if (hovered)
4010  {
4011  g.HoveredId = id;
4012  if (allow_key_modifiers || (!g.IO.KeyCtrl && !g.IO.KeyShift))
4013  {
4014  if (g.IO.MouseClicked[0])
4015  {
4016  if (pressed_on_click)
4017  {
4018  pressed = true;
4019  SetActiveId(0);
4020  }
4021  else
4022  {
4023  SetActiveId(id);
4024  }
4025  FocusWindow(window);
4026  }
4027  else if (repeat && g.ActiveId && ImGui::IsMouseClicked(0, true))
4028  {
4029  pressed = true;
4030  }
4031  }
4032  }
4033 
4034  bool held = false;
4035  if (g.ActiveId == id)
4036  {
4037  if (g.IO.MouseDown[0])
4038  {
4039  held = true;
4040  }
4041  else
4042  {
4043  if (hovered)
4044  pressed = true;
4045  SetActiveId(0);
4046  }
4047  }
4048 
4049  if (out_hovered) *out_hovered = hovered;
4050  if (out_held) *out_held = held;
4051 
4052  return pressed;
4053 }
4054 
4055 bool ImGui::Button(const char* label, const ImVec2& size_arg, bool repeat_when_held)
4056 {
4057  ImGuiState& g = *GImGui;
4058  ImGuiWindow* window = GetCurrentWindow();
4059  if (window->SkipItems)
4060  return false;
4061 
4062  const ImGuiStyle& style = g.Style;
4063  const ImGuiID id = window->GetID(label);
4064  const ImVec2 label_size = CalcTextSize(label, NULL, true);
4065 
4066  const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
4067  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
4068  ItemSize(bb);
4069  if (!ItemAdd(bb, &id))
4070  return false;
4071 
4072  bool hovered, held;
4073  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true, repeat_when_held);
4074 
4075  // Render
4076  const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
4077  RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
4078 
4079  const ImVec2 off = ImVec2(ImMax(0.0f, size.x - label_size.x) * 0.5f, ImMax(0.0f, size.y - label_size.y) * 0.5f); // Center (only applies if we explicitly gave a size bigger than the text size, which isn't the common path)
4080  RenderTextClipped(bb.Min + style.FramePadding + off, label, NULL, &label_size, bb.Max); // Render clip (only applies if we explicitly gave a size smaller than the text size, which isn't the commmon path)
4081 
4082  return pressed;
4083 }
4084 
4085 // Small buttons fits within text without additional spacing.
4086 bool ImGui::SmallButton(const char* label)
4087 {
4088  ImGuiState& g = *GImGui;
4089  ImGuiWindow* window = GetCurrentWindow();
4090  if (window->SkipItems)
4091  return false;
4092 
4093  const ImGuiStyle& style = g.Style;
4094  const ImGuiID id = window->GetID(label);
4095  const ImVec2 label_size = CalcTextSize(label, NULL, true);
4096 
4097  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + label_size + ImVec2(style.FramePadding.x*2,0));
4098  ItemSize(bb);
4099  if (!ItemAdd(bb, &id))
4100  return false;
4101 
4102  bool hovered, held;
4103  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
4104 
4105  // Render
4106  const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
4107  RenderFrame(bb.Min, bb.Max, col);
4108  RenderText(bb.Min + ImVec2(style.FramePadding.x,0), label);
4109 
4110  return pressed;
4111 }
4112 
4113 // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
4114 // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)
4115 bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size)
4116 {
4117  ImGuiWindow* window = GetCurrentWindow();
4118  if (window->SkipItems)
4119  return false;
4120 
4121  const ImGuiID id = window->GetID(str_id);
4122  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size);
4123  ItemSize(bb);
4124  if (!ItemAdd(bb, &id))
4125  return false;
4126 
4127  bool hovered, held;
4128  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
4129 
4130  return pressed;
4131 }
4132 
4133 // Upper-right button to close a window.
4134 static bool CloseWindowButton(bool* p_opened)
4135 {
4136  ImGuiWindow* window = GetCurrentWindow();
4137 
4138  const ImGuiID id = window->GetID("#CLOSE");
4139  const float size = window->TitleBarHeight() - 4.0f;
4140  const ImGuiAabb bb(window->Aabb().GetTR() + ImVec2(-3.0f-size,2.0f), window->Aabb().GetTR() + ImVec2(-3.0f,2.0f+size));
4141 
4142  bool hovered, held;
4143  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
4144 
4145  // Render
4146  const ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
4147  const ImVec2 center = bb.GetCenter();
4148  window->DrawList->AddCircleFilled(center, ImMax(2.0f,size*0.5f), col, 16);
4149 
4150  const float cross_extent = (size * 0.5f * 0.7071f) - 1.0f;
4151  if (hovered)
4152  {
4153  window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), window->Color(ImGuiCol_Text));
4154  window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), window->Color(ImGuiCol_Text));
4155  }
4156 
4157  if (p_opened != NULL && pressed)
4158  *p_opened = !*p_opened;
4159 
4160  return pressed;
4161 }
4162 
4163 void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
4164 {
4165  ImGuiWindow* window = GetCurrentWindow();
4166  if (window->SkipItems)
4167  return;
4168 
4169  ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size);
4170  if (border_col.w > 0.0f)
4171  bb.Max += ImVec2(2,2);
4172  ItemSize(bb);
4173  if (!ItemAdd(bb, NULL))
4174  return;
4175 
4176  if (border_col.w > 0.0f)
4177  {
4178  window->DrawList->AddRect(bb.Min, bb.Max, window->Color(border_col), 0.0f);
4179  window->DrawList->AddImage(user_texture_id, bb.Min+ImVec2(1,1), bb.Max-ImVec2(1,1), uv0, uv1, window->Color(tint_col));
4180  }
4181  else
4182  {
4183  window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, window->Color(tint_col));
4184  }
4185 }
4186 
4187 // frame_padding < 0: uses FramePadding from style (default)
4188 // frame_padding = 0: no framing
4189 // frame_padding > 0: set framing size
4190 // The color used are the button colors.
4191 bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
4192 {
4193  ImGuiState& g = *GImGui;
4194  ImGuiWindow* window = GetCurrentWindow();
4195  if (window->SkipItems)
4196  return false;
4197 
4198  const ImGuiStyle& style = g.Style;
4199 
4200  // Default to using texture ID as ID. User can still push string/integer prefixes.
4201  // We could hash the size/uv to create a unique ID but that would prevent the user from animating buttons.
4202  ImGui::PushID((void *)user_texture_id);
4203  const ImGuiID id = window->GetID("#image");
4204  ImGui::PopID();
4205 
4206  const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
4207  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size + padding*2);
4208  const ImGuiAabb image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
4209  ItemSize(bb);
4210  if (!ItemAdd(bb, &id))
4211  return false;
4212 
4213  bool hovered, held;
4214  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
4215 
4216  // Render
4217  const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
4218  if (padding.x > 0.0f || padding.y > 0.0f)
4219  RenderFrame(bb.Min, bb.Max, col);
4220  if (bg_col.w > 0.0f)
4221  window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, window->Color(bg_col));
4222  window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, window->Color(tint_col));
4223 
4224  return pressed;
4225 }
4226 
4227 // Start logging ImGui output to TTY
4228 void ImGui::LogToTTY(int max_depth)
4229 {
4230  ImGuiState& g = *GImGui;
4231  ImGuiWindow* window = GetCurrentWindow();
4232  if (g.LogEnabled)
4233  return;
4234 
4235  g.LogEnabled = true;
4236  g.LogFile = stdout;
4237  g.LogStartDepth = window->DC.TreeDepth;
4238  if (max_depth >= 0)
4239  g.LogAutoExpandMaxDepth = max_depth;
4240 }
4241 
4242 // Start logging ImGui output to given file
4243 void ImGui::LogToFile(int max_depth, const char* filename)
4244 {
4245  ImGuiState& g = *GImGui;
4246  ImGuiWindow* window = GetCurrentWindow();
4247  if (g.LogEnabled)
4248  return;
4249  if (!filename)
4250  filename = g.IO.LogFilename;
4251 
4252  g.LogFile = fopen(filename, "ab");
4253  if (!g.LogFile)
4254  {
4255  IM_ASSERT(g.LogFile != NULL); // Consider this an error
4256  return;
4257  }
4258  g.LogEnabled = true;
4259  g.LogStartDepth = window->DC.TreeDepth;
4260  if (max_depth >= 0)
4261  g.LogAutoExpandMaxDepth = max_depth;
4262 }
4263 
4264 // Start logging ImGui output to clipboard
4265 void ImGui::LogToClipboard(int max_depth)
4266 {
4267  ImGuiWindow* window = GetCurrentWindow();
4268  ImGuiState& g = *GImGui;
4269  if (g.LogEnabled)
4270  return;
4271 
4272  g.LogEnabled = true;
4273  g.LogFile = NULL;
4274  g.LogStartDepth = window->DC.TreeDepth;
4275  if (max_depth >= 0)
4276  g.LogAutoExpandMaxDepth = max_depth;
4277 }
4278 
4280 {
4281  ImGuiState& g = *GImGui;
4282  if (!g.LogEnabled)
4283  return;
4284 
4286  g.LogEnabled = false;
4287  if (g.LogFile != NULL)
4288  {
4289  if (g.LogFile == stdout)
4290  fflush(g.LogFile);
4291  else
4292  fclose(g.LogFile);
4293  g.LogFile = NULL;
4294  }
4295  if (g.LogClipboard->size() > 1)
4296  {
4297  if (g.IO.SetClipboardTextFn)
4298  g.IO.SetClipboardTextFn(g.LogClipboard->begin());
4299  g.LogClipboard->clear();
4300  }
4301 }
4302 
4303 // Helper to display logging buttons
4305 {
4306  ImGuiState& g = *GImGui;
4307 
4308  ImGui::PushID("LogButtons");
4309  const bool log_to_tty = ImGui::Button("Log To TTY");
4310  ImGui::SameLine();
4311  const bool log_to_file = ImGui::Button("Log To File");
4312  ImGui::SameLine();
4313  const bool log_to_clipboard = ImGui::Button("Log To Clipboard");
4314  ImGui::SameLine();
4315 
4316  ImGui::PushItemWidth(80.0f);
4318  ImGui::SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL);
4321  ImGui::PopID();
4322 
4323  // Start logging at the end of the function so that the buttons don't appear in the log
4324  if (log_to_tty)
4325  LogToTTY(g.LogAutoExpandMaxDepth);
4326  if (log_to_file)
4327  LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename);
4328  if (log_to_clipboard)
4329  LogToClipboard(g.LogAutoExpandMaxDepth);
4330 }
4331 
4332 bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
4333 {
4334  ImGuiState& g = *GImGui;
4335  ImGuiWindow* window = GetCurrentWindow();
4336  if (window->SkipItems)
4337  return false;
4338 
4339  const ImGuiStyle& style = g.Style;
4340 
4341  IM_ASSERT(str_id != NULL || label != NULL);
4342  if (str_id == NULL)
4343  str_id = label;
4344  if (label == NULL)
4345  label = str_id;
4346  const ImGuiID id = window->GetID(str_id);
4347 
4348  // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions)
4349  ImGuiStorage* storage = window->DC.StateStorage;
4350  bool opened;
4351  if (g.SetNextTreeNodeOpenedCond != 0)
4352  {
4353  if (g.SetNextTreeNodeOpenedCond & ImGuiSetCond_Always)
4354  {
4355  opened = g.SetNextTreeNodeOpenedVal;
4356  storage->SetInt(id, opened);
4357  }
4358  else
4359  {
4360  // We treat ImGuiSetCondition_Once and ImGuiSetCondition_FirstUseEver the same because tree node state are not saved persistently.
4361  const int stored_value = storage->GetInt(id, -1);
4362  if (stored_value == -1)
4363  {
4364  opened = g.SetNextTreeNodeOpenedVal;
4365  storage->SetInt(id, opened);
4366  }
4367  else
4368  {
4369  opened = stored_value != 0;
4370  }
4371  }
4372  g.SetNextTreeNodeOpenedCond = 0;
4373  }
4374  else
4375  {
4376  opened = storage->GetInt(id, default_open) != 0;
4377  }
4378 
4379  // Framed header expand a little outside the default padding
4380  const ImVec2 window_padding = window->WindowPadding();
4381  const ImVec2 label_size = CalcTextSize(label, NULL, true);
4382  const ImVec2 pos_min = window->DC.CursorPos;
4383  const ImVec2 pos_max = window->Pos + GetContentRegionMax();
4384  ImGuiAabb bb = ImGuiAabb(pos_min, ImVec2(pos_max.x, pos_min.y + label_size.y));
4385  if (display_frame)
4386  {
4387  bb.Min.x -= window_padding.x*0.5f - 1;
4388  bb.Max.x += window_padding.x*0.5f - 1;
4389  bb.Max.y += style.FramePadding.y * 2;
4390  }
4391 
4392  const ImGuiAabb text_bb(bb.Min, bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2*2,0) + label_size);
4393  ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
4394 
4395  // When logging is enabled, if automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behaviour).
4396  // NB- If we are above max depth we still allow manually opened nodes to be logged.
4397  if (g.LogEnabled && !display_frame && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
4398  opened = true;
4399 
4400  if (!ItemAdd(bb, &id))
4401  return opened;
4402 
4403  bool hovered, held;
4404  bool pressed = ButtonBehaviour(display_frame ? bb : text_bb, id, &hovered, &held, false);
4405  if (pressed)
4406  {
4407  opened = !opened;
4408  storage->SetInt(id, opened);
4409  }
4410 
4411  // Render
4412  const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
4413  if (display_frame)
4414  {
4415  // Framed type
4416  RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
4417  RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true);
4418  if (g.LogEnabled)
4419  {
4420  // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
4421  const char log_prefix[] = "\n##";
4422  LogText(bb.Min + style.FramePadding, log_prefix, log_prefix+3);
4423  }
4424  RenderText(bb.Min + style.FramePadding + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label);
4425  if (g.LogEnabled)
4426  {
4427  const char log_suffix[] = "##";
4428  LogText(bb.Min + style.FramePadding, log_suffix, log_suffix+2);
4429  }
4430  }
4431  else
4432  {
4433  // Unframed typed for tree nodes
4434  if ((held && hovered) || hovered)
4435  RenderFrame(bb.Min, bb.Max, col, false);
4436  RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, window->FontSize()*0.15f), opened, 0.70f, false);
4437  if (g.LogEnabled)
4438  LogText(bb.Min, ">");
4439  RenderText(bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label);
4440  }
4441 
4442  return opened;
4443 }
4444 
4446 {
4447  ImGuiState& g = *GImGui;
4448  ImGuiWindow* window = GetCurrentWindow();
4449  if (window->SkipItems)
4450  return;
4451 
4452  const ImGuiStyle& style = g.Style;
4453  const float line_height = window->FontSize();
4454  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(line_height, line_height));
4455  ItemSize(bb);
4456  if (!ItemAdd(bb, NULL))
4457  return;
4458 
4459  // Render
4460  const float bullet_size = line_height*0.15f;
4461  window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + line_height*0.5f, line_height*0.5f), bullet_size, window->Color(ImGuiCol_Text));
4462 
4463  // Stay on same line
4464  ImGui::SameLine(0, -1);
4465 }
4466 
4467 // Text with a little bullet aligned to the typical tree node.
4468 void ImGui::BulletTextV(const char* fmt, va_list args)
4469 {
4470  ImGuiState& g = *GImGui;
4471  ImGuiWindow* window = GetCurrentWindow();
4472  if (window->SkipItems)
4473  return;
4474 
4475  static char buf[1024];
4476  const char* text_begin = buf;
4477  const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
4478 
4479  const ImGuiStyle& style = g.Style;
4480  const float line_height = window->FontSize();
4481  const ImVec2 label_size = CalcTextSize(text_begin, text_end, true);
4482  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(line_height + (label_size.x > 0.0f ? (style.FramePadding.x*2) : 0.0f),0) + label_size); // Empty text doesn't add padding
4483  ItemSize(bb);
4484  if (!ItemAdd(bb, NULL))
4485  return;
4486 
4487  // Render
4488  const float bullet_size = line_height*0.15f;
4489  window->DrawList->AddCircleFilled(bb.Min + ImVec2(style.FramePadding.x + line_height*0.5f, line_height*0.5f), bullet_size, window->Color(ImGuiCol_Text));
4490  RenderText(bb.Min+ImVec2(window->FontSize() + style.FramePadding.x*2,0), text_begin, text_end);
4491 }
4492 
4493 void ImGui::BulletText(const char* fmt, ...)
4494 {
4495  va_list args;
4496  va_start(args, fmt);
4497  BulletTextV(fmt, args);
4498  va_end(args);
4499 }
4500 
4501 // If returning 'true' the node is open and the user is responsible for calling TreePop
4502 bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
4503 {
4504  static char buf[1024];
4505  ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
4506 
4507  if (!str_id || !str_id[0])
4508  str_id = fmt;
4509 
4510  ImGui::PushID(str_id);
4511  const bool opened = ImGui::CollapsingHeader(buf, "", false); // do not add to the ID so that TreeNodeSetOpen can access
4512  ImGui::PopID();
4513 
4514  if (opened)
4515  ImGui::TreePush(str_id);
4516 
4517  return opened;
4518 }
4519 
4520 bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
4521 {
4522  va_list args;
4523  va_start(args, fmt);
4524  bool s = TreeNodeV(str_id, fmt, args);
4525  va_end(args);
4526  return s;
4527 }
4528 
4529 // If returning 'true' the node is open and the user is responsible for calling TreePop
4530 bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
4531 {
4532  static char buf[1024];
4533  ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
4534 
4535  if (!ptr_id)
4536  ptr_id = fmt;
4537 
4538  ImGui::PushID(ptr_id);
4539  const bool opened = ImGui::CollapsingHeader(buf, "", false);
4540  ImGui::PopID();
4541 
4542  if (opened)
4543  ImGui::TreePush(ptr_id);
4544 
4545  return opened;
4546 }
4547 
4548 bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
4549 {
4550  va_list args;
4551  va_start(args, fmt);
4552  bool s = TreeNodeV(ptr_id, fmt, args);
4553  va_end(args);
4554  return s;
4555 }
4556 
4557 bool ImGui::TreeNode(const char* str_label_id)
4558 {
4559  return TreeNode(str_label_id, "%s", str_label_id);
4560 }
4561 
4563 {
4564  ImGuiState& g = *GImGui;
4565  g.SetNextTreeNodeOpenedVal = opened;
4566  g.SetNextTreeNodeOpenedCond = cond ? cond : ImGuiSetCond_Always;
4567 }
4568 
4569 void ImGui::PushID(const char* str_id)
4570 {
4571  ImGuiWindow* window = GetCurrentWindow();
4572  window->IDStack.push_back(window->GetID(str_id));
4573 }
4574 
4575 void ImGui::PushID(const void* ptr_id)
4576 {
4577  ImGuiWindow* window = GetCurrentWindow();
4578  window->IDStack.push_back(window->GetID(ptr_id));
4579 }
4580 
4581 void ImGui::PushID(const int int_id)
4582 {
4583  const void* ptr_id = (void*)(intptr_t)int_id;
4584  ImGuiWindow* window = GetCurrentWindow();
4585  window->IDStack.push_back(window->GetID(ptr_id));
4586 }
4587 
4589 {
4590  ImGuiWindow* window = GetCurrentWindow();
4591  window->IDStack.pop_back();
4592 }
4593 
4594 ImGuiID ImGui::GetID(const char* str_id)
4595 {
4596  ImGuiWindow* window = GetCurrentWindow();
4597  return window->GetID(str_id);
4598 }
4599 
4600 ImGuiID ImGui::GetID(const void* ptr_id)
4601 {
4602  ImGuiWindow* window = GetCurrentWindow();
4603  return window->GetID(ptr_id);
4604 }
4605 
4606 // User can input math operators (e.g. +100) to edit a numerical values.
4607 // NB: only call right after InputText because we are using its InitialValue storage
4608 static void ApplyNumericalTextInput(const char* buf, float *v)
4609 {
4610  while (ImCharIsSpace(*buf))
4611  buf++;
4612 
4613  // We don't support '-' op because it would conflict with inputing negative value.
4614  // Instead you can use +-100 to subtract from an existing value
4615  char op = buf[0];
4616  if (op == '+' || op == '*' || op == '/')
4617  {
4618  buf++;
4619  while (ImCharIsSpace(*buf))
4620  buf++;
4621  }
4622  else
4623  {
4624  op = 0;
4625  }
4626  if (!buf[0])
4627  return;
4628 
4629  float ref_v = *v;
4630  if (op)
4631  if (sscanf(GImGui->InputTextState.InitialText, "%f", &ref_v) < 1)
4632  return;
4633 
4634  float op_v = 0.0f;
4635  if (sscanf(buf, "%f", &op_v) < 1)
4636  return;
4637 
4638  if (op == '+')
4639  *v = ref_v + op_v;
4640  else if (op == '*')
4641  *v = ref_v * op_v;
4642  else if (op == '/')
4643  {
4644  if (op_v == 0.0f)
4645  return;
4646  *v = ref_v / op_v;
4647  }
4648  else
4649  *v = op_v;
4650 }
4651 
4652 // Use power!=1.0 for logarithmic sliders.
4653 // Adjust display_format to decorate the value with a prefix or a suffix.
4654 bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power)
4655 {
4656  ImGuiState& g = *GImGui;
4657  ImGuiWindow* window = GetCurrentWindow();
4658  if (window->SkipItems)
4659  return false;
4660 
4661  const ImGuiStyle& style = g.Style;
4662  const ImGuiID id = window->GetID(label);
4663  const float w = ImGui::CalcItemWidth();
4664 
4665  if (!display_format)
4666  display_format = "%.3f";
4667 
4668  // Parse display precision back from the display format string
4669  int decimal_precision = 3;
4670  if (const char* p = strchr(display_format, '%'))
4671  {
4672  p++;
4673  while (*p >= '0' && *p <= '9')
4674  p++;
4675  if (*p == '.')
4676  {
4677  decimal_precision = atoi(p+1);
4678  if (decimal_precision < 0 || decimal_precision > 10)
4679  decimal_precision = 3;
4680  }
4681  }
4682 
4683  const ImVec2 label_size = CalcTextSize(label, NULL, true);
4684  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
4685  const ImGuiAabb slider_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
4686  const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
4687 
4688  // NB- we don't call ItemSize() yet becausae we may turn into a text edit box later in the function
4689  if (!ItemAdd(slider_bb, &id))
4690  {
4691  ItemSize(bb);
4692  return false;
4693  }
4694 
4695  const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id);
4696 
4697  const bool is_unbound = v_min == -FLT_MAX || v_min == FLT_MAX || v_max == -FLT_MAX || v_max == FLT_MAX;
4698 
4699  const float grab_size_in_units = 1.0f; // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision?
4700  float grab_size_in_pixels;
4701  if (decimal_precision > 0 || is_unbound)
4702  grab_size_in_pixels = style.GrabMinSize;
4703  else
4704  grab_size_in_pixels = ImMax(grab_size_in_units * (w / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders
4705  const float slider_effective_w = slider_bb.GetWidth() - grab_size_in_pixels;
4706  const float slider_effective_x1 = slider_bb.Min.x + grab_size_in_pixels*0.5f;
4707  const float slider_effective_x2 = slider_bb.Max.x - grab_size_in_pixels*0.5f;
4708 
4709  // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f
4710  float linear_zero_pos = 0.0f; // 0.0->1.0f
4711  if (!is_unbound)
4712  {
4713  if (v_min * v_max < 0.0f)
4714  {
4715  // Different sign
4716  const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power);
4717  const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power);
4718  linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0);
4719  }
4720  else
4721  {
4722  // Same sign
4723  linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
4724  }
4725  }
4726 
4727  const bool hovered = IsHovered(slider_bb, id);
4728  if (hovered)
4729  g.HoveredId = id;
4730 
4731  bool start_text_input = false;
4732  if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
4733  {
4734  SetActiveId(id);
4735  FocusWindow(window);
4736 
4737  const bool is_ctrl_down = g.IO.KeyCtrl;
4738  if (tab_focus_requested || is_ctrl_down || is_unbound)
4739  {
4740  start_text_input = true;
4741  g.SliderAsInputTextId = 0;
4742  }
4743  }
4744 
4745  // Tabbing or CTRL-clicking through slider turns into an input box
4746  bool value_changed = false;
4747  if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId))
4748  {
4749  char text_buf[64];
4750  ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
4751 
4752  SetActiveId(g.SliderAsInputTextId);
4753  g.HoveredId = 0;
4754  window->FocusItemUnregister(); // Our replacement slider will override the focus ID (registered previously to allow for a TAB focus to happen)
4756  if (g.SliderAsInputTextId == 0)
4757  {
4758  // First frame
4759  IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible)
4760  g.SliderAsInputTextId = g.ActiveId;
4761  g.HoveredId = id;
4762  }
4763  else if (g.ActiveId != g.SliderAsInputTextId)
4764  {
4765  // Release
4766  g.SliderAsInputTextId = 0;
4767  }
4768  if (value_changed)
4769  {
4770  ApplyNumericalTextInput(text_buf, v);
4771  }
4772  return value_changed;
4773  }
4774 
4775  ItemSize(bb);
4776  RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
4777 
4778  // Process clicking on the slider
4779  if (g.ActiveId == id)
4780  {
4781  if (g.IO.MouseDown[0])
4782  {
4783  if (!is_unbound)
4784  {
4785  const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f);
4786 
4787  // Linear slider
4788  //float new_value = ImLerp(v_min, v_max, normalized_pos);
4789 
4790  // Account for logarithmic scale on both sides of the zero
4791  float new_value;
4792  if (normalized_pos < linear_zero_pos)
4793  {
4794  // Negative: rescale to the negative range before powering
4795  float a = 1.0f - (normalized_pos / linear_zero_pos);
4796  a = powf(a, power);
4797  new_value = ImLerp(ImMin(v_max,0.f), v_min, a);
4798  }
4799  else
4800  {
4801  // Positive: rescale to the positive range before powering
4802  float a;
4803  if (fabsf(linear_zero_pos - 1.0f) > 1.e-6)
4804  a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos);
4805  else
4806  a = normalized_pos;
4807  a = powf(a, power);
4808  new_value = ImLerp(ImMax(v_min,0.0f), v_max, a);
4809  }
4810 
4811  // Round past decimal precision
4812  // 0->1, 1->0.1, 2->0.01, etc.
4813  // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0
4814  const float min_step = 1.0f / powf(10.0f, (float)decimal_precision);
4815  const float remainder = fmodf(new_value, min_step);
4816  if (remainder <= min_step*0.5f)
4817  new_value -= remainder;
4818  else
4819  new_value += (min_step - remainder);
4820 
4821  if (*v != new_value)
4822  {
4823  *v = new_value;
4824  value_changed = true;
4825  }
4826  }
4827  }
4828  else
4829  {
4830  SetActiveId(0);
4831  }
4832  }
4833 
4834  if (!is_unbound)
4835  {
4836  // Linear slider
4837  // const float grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min);
4838 
4839  // Calculate slider grab positioning
4840  float grab_t;
4841  float v_clamped = ImClamp(*v, v_min, v_max);
4842  if (v_clamped < 0.0f)
4843  {
4844  const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min);
4845  grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos;
4846  }
4847  else
4848  {
4849  const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min));
4850  grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos);
4851  }
4852 
4853  // Draw
4854  const float grab_x = ImLerp(slider_effective_x1, slider_effective_x2, grab_t);
4855  const ImGuiAabb grab_bb(ImVec2(grab_x-grab_size_in_pixels*0.5f,frame_bb.Min.y+2.0f), ImVec2(grab_x+grab_size_in_pixels*0.5f,frame_bb.Max.y-2.0f));
4856  window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab));
4857  }
4858 
4859  // Draw value using user-provided display format so user can add prefix/suffix/decorations to the value.
4860  char value_buf[64];
4861  char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);
4862  const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true);
4863  RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x + style.FramePadding.x, slider_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max);
4864 
4865  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, slider_bb.Min.y), label);
4866 
4867  return value_changed;
4868 }
4869 
4870 bool ImGui::SliderAngle(const char* label, float* v, float v_degrees_min, float v_degrees_max)
4871 {
4872  float v_deg = *v * 360.0f / (2*PI);
4873  bool value_changed = ImGui::SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, "%.0f deg", 1.0f);
4874  *v = v_deg * (2*PI) / 360.0f;
4875  return value_changed;
4876 }
4877 
4878 bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format)
4879 {
4880  if (!display_format)
4881  display_format = "%.0f";
4882  float v_f = (float)*v;
4883  bool value_changed = ImGui::SliderFloat(label, &v_f, (float)v_min, (float)v_max, display_format, 1.0f);
4884  *v = (int)v_f;
4885  return value_changed;
4886 }
4887 
4888 // Add multiple sliders on 1 line for compact edition of multiple components
4889 static bool SliderFloatN(const char* label, float v[3], int components, float v_min, float v_max, const char* display_format, float power)
4890 {
4891  ImGuiState& g = *GImGui;
4892  ImGuiWindow* window = GetCurrentWindow();
4893  if (window->SkipItems)
4894  return false;
4895 
4896  const ImGuiStyle& style = g.Style;
4897  const float w_full = ImGui::CalcItemWidth();
4898  const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
4899  const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
4900 
4901  bool value_changed = false;
4902  ImGui::PushID(label);
4903  ImGui::PushItemWidth(w_item_one);
4904  for (int i = 0; i < components; i++)
4905  {
4906  ImGui::PushID(i);
4907  if (i + 1 == components)
4908  {
4910  ImGui::PushItemWidth(w_item_last);
4911  }
4912  value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power);
4913  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
4914  ImGui::PopID();
4915  }
4917  ImGui::PopID();
4918 
4920 
4921  return value_changed;
4922 }
4923 
4924 bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power)
4925 {
4926  return SliderFloatN(label, v, 2, v_min, v_max, display_format, power);
4927 }
4928 
4929 bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power)
4930 {
4931  return SliderFloatN(label, v, 3, v_min, v_max, display_format, power);
4932 }
4933 
4934 bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* display_format, float power)
4935 {
4936  return SliderFloatN(label, v, 4, v_min, v_max, display_format, power);
4937 }
4938 
4939 static bool SliderIntN(const char* label, int v[3], int components, int v_min, int v_max, const char* display_format)
4940 {
4941  ImGuiState& g = *GImGui;
4942  ImGuiWindow* window = GetCurrentWindow();
4943  if (window->SkipItems)
4944  return false;
4945 
4946  const ImGuiStyle& style = g.Style;
4947  const float w_full = ImGui::CalcItemWidth();
4948  const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
4949  const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
4950 
4951  bool value_changed = false;
4952  ImGui::PushID(label);
4953  ImGui::PushItemWidth(w_item_one);
4954  for (int i = 0; i < components; i++)
4955  {
4956  ImGui::PushID(i);
4957  if (i + 1 == components)
4958  {
4960  ImGui::PushItemWidth(w_item_last);
4961  }
4962  value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format);
4963  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
4964  ImGui::PopID();
4965  }
4967  ImGui::PopID();
4968 
4970 
4971  return value_changed;
4972 }
4973 
4974 bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format)
4975 {
4976  return SliderIntN(label, v, 2, v_min, v_max, display_format);
4977 }
4978 
4979 bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format)
4980 {
4981  return SliderIntN(label, v, 3, v_min, v_max, display_format);
4982 }
4983 
4984 bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format)
4985 {
4986  return SliderIntN(label, v, 4, v_min, v_max, display_format);
4987 }
4988 
4990 {
4993 };
4994 
4995 static void Plot(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
4996 {
4997  ImGuiState& g = *GImGui;
4998  ImGuiWindow* window = GetCurrentWindow();
4999  if (window->SkipItems)
5000  return;
5001 
5002  const ImGuiStyle& style = g.Style;
5003 
5004  const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
5005  if (graph_size.x == 0.0f)
5006  graph_size.x = ImGui::CalcItemWidth();
5007  if (graph_size.y == 0.0f)
5008  graph_size.y = label_size.y;
5009 
5010  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y) + style.FramePadding*2.0f);
5011  const ImGuiAabb graph_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
5012  const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
5013  ItemSize(bb);
5014  if (!ItemAdd(bb, NULL))
5015  return;
5016 
5017  // Determine scale from values if not specified
5018  if (scale_min == FLT_MAX || scale_max == FLT_MAX)
5019  {
5020  float v_min = FLT_MAX;
5021  float v_max = -FLT_MAX;
5022  for (int i = 0; i < values_count; i++)
5023  {
5024  const float v = values_getter(data, i);
5025  v_min = ImMin(v_min, v);
5026  v_max = ImMax(v_max, v);
5027  }
5028  if (scale_min == FLT_MAX)
5029  scale_min = v_min;
5030  if (scale_max == FLT_MAX)
5031  scale_max = v_max;
5032  }
5033 
5034  RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
5035 
5036  int res_w = ImMin((int)graph_size.x, values_count);
5037  if (plot_type == ImGuiPlotType_Lines)
5038  res_w -= 1;
5039 
5040  // Tooltip on hover
5041  int v_hovered = -1;
5042  if (IsMouseHoveringBox(graph_bb))
5043  {
5044  const float t = ImClamp((g.IO.MousePos.x - graph_bb.Min.x) / (graph_bb.Max.x - graph_bb.Min.x), 0.0f, 0.9999f);
5045  const int v_idx = (int)(t * (values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0)));
5046  IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5047 
5048  const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
5049  const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
5050  if (plot_type == ImGuiPlotType_Lines)
5051  ImGui::SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
5052  else if (plot_type == ImGuiPlotType_Histogram)
5053  ImGui::SetTooltip("%d: %8.4g", v_idx, v0);
5054  v_hovered = v_idx;
5055  }
5056 
5057  const float t_step = 1.0f / (float)res_w;
5058 
5059  float v0 = values_getter(data, (0 + values_offset) % values_count);
5060  float t0 = 0.0f;
5061  ImVec2 p0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) );
5062 
5063  const ImU32 col_base = window->Color((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
5064  const ImU32 col_hovered = window->Color((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
5065 
5066  for (int n = 0; n < res_w; n++)
5067  {
5068  const float t1 = t0 + t_step;
5069  const int v_idx = (int)(t0 * values_count);
5070  IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5071  const float v1 = values_getter(data, (v_idx + values_offset + 1) % values_count);
5072  const ImVec2 p1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );
5073 
5074  // NB- Draw calls are merged together by the DrawList system.
5075  if (plot_type == ImGuiPlotType_Lines)
5076  window->DrawList->AddLine(ImLerp(graph_bb.Min, graph_bb.Max, p0), ImLerp(graph_bb.Min, graph_bb.Max, p1), v_hovered == v_idx ? col_hovered : col_base);
5077  else if (plot_type == ImGuiPlotType_Histogram)
5078  window->DrawList->AddRectFilled(ImLerp(graph_bb.Min, graph_bb.Max, p0), ImLerp(graph_bb.Min, graph_bb.Max, ImVec2(p1.x, 1.0f))+ImVec2(-1,0), v_hovered == v_idx ? col_hovered : col_base);
5079 
5080  t0 = t1;
5081  p0 = p1;
5082  }
5083 
5084  // Text overlay
5085  if (overlay_text)
5086  RenderText(ImVec2(graph_bb.GetCenter().x - ImGui::CalcTextSize(overlay_text, NULL, true).x*0.5f, frame_bb.Min.y + style.FramePadding.y), overlay_text);
5087 
5088  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, graph_bb.Min.y), label);
5089 }
5090 
5091 struct ImGuiPlotArrayGetterData
5092 {
5093  const float* Values;
5094  size_t Stride;
5095 
5096  ImGuiPlotArrayGetterData(const float* values, size_t stride) { Values = values; Stride = stride; }
5097 };
5098 
5099 static float Plot_ArrayGetter(void* data, int idx)
5100 {
5101  ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;
5102  const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
5103  return v;
5104 }
5105 
5106 void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, size_t stride)
5107 {
5108  ImGuiPlotArrayGetterData data(values, stride);
5109  Plot(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5110 }
5111 
5112 void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
5113 {
5114  Plot(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5115 }
5116 
5117 void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, size_t stride)
5118 {
5119  ImGuiPlotArrayGetterData data(values, stride);
5120  Plot(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5121 }
5122 
5123 void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
5124 {
5125  Plot(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5126 }
5127 
5128 bool ImGui::Checkbox(const char* label, bool* v)
5129 {
5130  ImGuiState& g = *GImGui;
5131  ImGuiWindow* window = GetCurrentWindow();
5132  if (window->SkipItems)
5133  return false;
5134 
5135  const ImGuiStyle& style = g.Style;
5136  const ImGuiID id = window->GetID(label);
5137  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5138 
5139  const ImGuiAabb check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2));
5140  ItemSize(check_bb);
5141 
5142  ImGuiAabb total_bb = check_bb;
5143  if (label_size.x > 0)
5144  SameLine(0, (int)style.ItemInnerSpacing.x);
5145  const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);
5146  if (label_size.x > 0)
5147  {
5148  ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
5149  total_bb = ImGuiAabb(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
5150  }
5151 
5152  if (!ItemAdd(total_bb, &id))
5153  return false;
5154 
5155  bool hovered, held;
5156  bool pressed = ButtonBehaviour(total_bb, id, &hovered, &held, true);
5157  if (pressed)
5158  *v = !(*v);
5159 
5160  RenderFrame(check_bb.Min, check_bb.Max, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
5161  if (*v)
5162  {
5163  const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
5164  const float pad = check_sz < 8.0f ? 1.0f : check_sz < 13.0f ? 2.0f : 3.0f;
5165  window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), window->Color(ImGuiCol_CheckMark), style.FrameRounding);
5166  }
5167 
5168  if (g.LogEnabled)
5169  LogText(text_bb.GetTL(), *v ? "[x]" : "[ ]");
5170  RenderText(text_bb.GetTL(), label);
5171 
5172  return pressed;
5173 }
5174 
5175 bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
5176 {
5177  bool v = (*flags & flags_value) ? true : false;
5178  bool pressed = ImGui::Checkbox(label, &v);
5179  if (v)
5180  *flags |= flags_value;
5181  else
5182  *flags &= ~flags_value;
5183  return pressed;
5184 }
5185 
5186 bool ImGui::RadioButton(const char* label, bool active)
5187 {
5188  ImGuiState& g = *GImGui;
5189  ImGuiWindow* window = GetCurrentWindow();
5190  if (window->SkipItems)
5191  return false;
5192 
5193  const ImGuiStyle& style = g.Style;
5194  const ImGuiID id = window->GetID(label);
5195  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5196 
5197  const ImGuiAabb check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1));
5198  ItemSize(check_bb);
5199 
5200  ImGuiAabb total_bb = check_bb;
5201  if (label_size.x > 0)
5202  SameLine(0, (int)style.ItemInnerSpacing.x);
5203  const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
5204  if (label_size.x > 0)
5205  {
5206  ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
5207  total_bb.Add(text_bb);
5208  }
5209 
5210  if (!ItemAdd(total_bb, &id))
5211  return false;
5212 
5213  ImVec2 center = check_bb.GetCenter();
5214  center.x = (float)(int)center.x + 0.5f;
5215  center.y = (float)(int)center.y + 0.5f;
5216  const float radius = check_bb.GetHeight() * 0.5f;
5217 
5218  bool hovered, held;
5219  bool pressed = ButtonBehaviour(total_bb, id, &hovered, &held, true);
5220 
5221  window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16);
5222  if (active)
5223  {
5224  const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
5225  const float pad = check_sz < 8.0f ? 1.0f : check_sz < 13.0f ? 2.0f : 3.0f;
5226  window->DrawList->AddCircleFilled(center, radius-pad, window->Color(ImGuiCol_CheckMark), 16);
5227  }
5228 
5229  if (window->Flags & ImGuiWindowFlags_ShowBorders)
5230  {
5231  window->DrawList->AddCircle(center+ImVec2(1,1), radius, window->Color(ImGuiCol_BorderShadow), 16);
5232  window->DrawList->AddCircle(center, radius, window->Color(ImGuiCol_Border), 16);
5233  }
5234 
5235  if (g.LogEnabled)
5236  LogText(text_bb.GetTL(), active ? "(x)" : "( )");
5237  RenderText(text_bb.GetTL(), label);
5238 
5239  return pressed;
5240 }
5241 
5242 bool ImGui::RadioButton(const char* label, int* v, int v_button)
5243 {
5244  const bool pressed = ImGui::RadioButton(label, *v == v_button);
5245  if (pressed)
5246  {
5247  *v = v_button;
5248  }
5249  return pressed;
5250 }
5251 
5252 // Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)
5253 static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return (int)ImStrlenW(obj->Text); }
5254 static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->Text[idx]; }
5255 static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { (void)line_start_idx; return obj->Font->CalcTextSizeW(obj->FontSize, FLT_MAX, &obj->Text[char_idx], &obj->Text[char_idx]+1, NULL).x; }
5256 static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; }
5258 static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
5259 {
5260  const ImWchar* text_remaining = NULL;
5261  const ImVec2 size = obj->Font->CalcTextSizeW(obj->FontSize, FLT_MAX, obj->Text + line_start_idx, NULL, &text_remaining);
5262  r->x0 = 0.0f;
5263  r->x1 = size.x;
5264  r->baseline_y_delta = size.y;
5265  r->ymin = 0.0f;
5266  r->ymax = size.y;
5267  r->num_chars = (int)(text_remaining - (obj->Text + line_start_idx));
5268 }
5269 
5270 static bool is_separator(unsigned int c) { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
5271 #define STB_TEXTEDIT_IS_SPACE(CH) ( ImCharIsSpace((unsigned int)CH) || is_separator((unsigned int)CH) )
5272 static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
5273 {
5274  ImWchar* dst = obj->Text + pos;
5275 
5276  // We maintain our buffer length in both UTF-8 and wchar formats
5277  obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
5278  obj->CurLenW -= n;
5279 
5280  // Offset remaining text
5281  const ImWchar* src = obj->Text + pos + n;
5282  while (ImWchar c = *src++)
5283  *dst++ = c;
5284  *dst = '\0';
5285 }
5286 
5287 static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
5288 {
5289  const size_t text_len = obj->CurLenW;
5290  if ((size_t)new_text_len + text_len + 1 > IM_ARRAYSIZE(obj->Text))
5291  return false;
5292 
5293  const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
5294  if ((size_t)new_text_len_utf8 + obj->CurLenA + 1 > obj->BufSizeA)
5295  return false;
5296 
5297  if (pos != (int)text_len)
5298  memmove(obj->Text + (size_t)pos + new_text_len, obj->Text + (size_t)pos, (text_len - (size_t)pos) * sizeof(ImWchar));
5299  memcpy(obj->Text + (size_t)pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
5300 
5301  obj->CurLenW += new_text_len;
5302  obj->CurLenA += new_text_len_utf8;
5303  obj->Text[obj->CurLenW] = '\0';
5304 
5305  return true;
5306 }
5307 
5308 enum
5309 {
5310  STB_TEXTEDIT_K_LEFT = 1 << 16, // keyboard input to move cursor left
5311  STB_TEXTEDIT_K_RIGHT, // keyboard input to move cursor right
5312  STB_TEXTEDIT_K_UP, // keyboard input to move cursor up
5313  STB_TEXTEDIT_K_DOWN, // keyboard input to move cursor down
5314  STB_TEXTEDIT_K_LINESTART, // keyboard input to move cursor to start of line
5315  STB_TEXTEDIT_K_LINEEND, // keyboard input to move cursor to end of line
5316  STB_TEXTEDIT_K_TEXTSTART, // keyboard input to move cursor to start of text
5317  STB_TEXTEDIT_K_TEXTEND, // keyboard input to move cursor to end of text
5318  STB_TEXTEDIT_K_DELETE, // keyboard input to delete selection or character under cursor
5319  STB_TEXTEDIT_K_BACKSPACE, // keyboard input to delete selection or character left of cursor
5320  STB_TEXTEDIT_K_UNDO, // keyboard input to perform undo
5321  STB_TEXTEDIT_K_REDO, // keyboard input to perform redo
5322  STB_TEXTEDIT_K_WORDLEFT, // keyboard input to move cursor left one word
5323  STB_TEXTEDIT_K_WORDRIGHT, // keyboard input to move cursor right one word
5325 };
5326 
5327 #ifdef IMGUI_STB_NAMESPACE
5328 namespace IMGUI_STB_NAMESPACE
5329 {
5330 #endif
5331 #define STB_TEXTEDIT_IMPLEMENTATION
5332 #include "stb_textedit.h"
5333 #ifdef IMGUI_STB_NAMESPACE
5334 }
5335 #endif
5336 
5337 void ImGuiTextEditState::OnKeyPressed(int key)
5338 {
5339  stb_textedit_key(this, &StbState, key);
5340  CursorAnimReset();
5341 }
5342 
5343 void ImGuiTextEditState::UpdateScrollOffset()
5344 {
5345  // Scroll in chunks of quarter width
5346  const float scroll_x_increment = Width * 0.25f;
5347  const float cursor_offset_x = Font->CalcTextSizeW(FontSize, FLT_MAX, Text, Text+StbState.cursor, NULL).x;
5348  if (ScrollX > cursor_offset_x)
5349  ScrollX = ImMax(0.0f, cursor_offset_x - scroll_x_increment);
5350  else if (ScrollX < cursor_offset_x - Width)
5351  ScrollX = cursor_offset_x - Width + scroll_x_increment;
5352 }
5353 
5354 ImVec2 ImGuiTextEditState::CalcDisplayOffsetFromCharIdx(int i) const
5355 {
5356  const ImWchar* text_start = GetTextPointerClippedW(Font, FontSize, Text, ScrollX, NULL);
5357  const ImWchar* text_end = (Text+i >= text_start) ? Text+i : text_start; // Clip if requested character is outside of display
5358  IM_ASSERT(text_end >= text_start);
5359 
5360  const ImVec2 offset = Font->CalcTextSizeW(FontSize, Width, text_start, text_end, NULL);
5361  return offset;
5362 }
5363 
5364 // [Static]
5365 const char* ImGuiTextEditState::GetTextPointerClippedA(ImFont* font, float font_size, const char* text, float width, ImVec2* out_text_size)
5366 {
5367  if (width <= 0.0f)
5368  return text;
5369 
5370  const char* text_clipped_end = NULL;
5371  const ImVec2 text_size = font->CalcTextSizeA(font_size, width, 0.0f, text, NULL, &text_clipped_end);
5372  if (out_text_size)
5373  *out_text_size = text_size;
5374  return text_clipped_end;
5375 }
5376 
5377 // [Static]
5378 const ImWchar* ImGuiTextEditState::GetTextPointerClippedW(ImFont* font, float font_size, const ImWchar* text, float width, ImVec2* out_text_size)
5379 {
5380  if (width <= 0.0f)
5381  return text;
5382 
5383  const ImWchar* text_clipped_end = NULL;
5384  const ImVec2 text_size = font->CalcTextSizeW(font_size, width, text, NULL, &text_clipped_end);
5385  if (out_text_size)
5386  *out_text_size = text_size;
5387  return text_clipped_end;
5388 }
5389 
5390 // [Static]
5391 void ImGuiTextEditState::RenderTextScrolledClipped(ImFont* font, float font_size, const char* buf, ImVec2 pos, float width, float scroll_x)
5392 {
5393  // NB- We start drawing at character boundary
5394  ImVec2 text_size;
5395  const char* text_start = GetTextPointerClippedA(font, font_size, buf, scroll_x, NULL);
5396  const char* text_end = GetTextPointerClippedA(font, font_size, text_start, width, &text_size);
5397 
5398  // We need to test for the possibility of malformed UTF-8 (instead of just text_end[0] != 0)
5399  unsigned int text_end_char = 0;
5400  ImTextCharFromUtf8(&text_end_char, text_end, NULL);
5401 
5402  // Draw a little clip symbol if we've got text on either left or right of the box
5403  const char symbol_c = '~';
5404  const float symbol_w = font_size*0.40f; // FIXME: compute correct width
5405  const float clip_begin = (text_start > buf && text_start < text_end) ? symbol_w : 0.0f;
5406  const float clip_end = (text_end_char != 0 && text_end > text_start) ? symbol_w : 0.0f;
5407 
5408  // Draw text
5409  RenderText(pos+ImVec2(clip_begin,0), text_start+(clip_begin>0.0f?1:0), text_end-(clip_end>0.0f?1:0), false);
5410 
5411  // Draw the clip symbol
5412  const char s[2] = {symbol_c,'\0'};
5413  if (clip_begin > 0.0f)
5414  RenderText(pos, s);
5415  if (clip_end > 0.0f)
5416  RenderText(pos+ImVec2(width-clip_end,0.0f), s);
5417 }
5418 
5419 bool ImGui::InputFloat(const char* label, float *v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags)
5420 {
5421  ImGuiState& g = *GImGui;
5422  ImGuiWindow* window = GetCurrentWindow();
5423  if (window->SkipItems)
5424  return false;
5425 
5426  const ImGuiStyle& style = g.Style;
5427  const float w = ImGui::CalcItemWidth();
5428  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5429  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
5430 
5431  ImGui::PushID(label);
5432  const float button_sz = window->FontSize();
5433  if (step > 0.0f)
5434  ImGui::PushItemWidth(ImMax(1.0f, w - (button_sz + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*2));
5435 
5436  char buf[64];
5437  if (decimal_precision < 0)
5438  ImFormatString(buf, IM_ARRAYSIZE(buf), "%f", *v); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits?
5439  else
5440  ImFormatString(buf, IM_ARRAYSIZE(buf), "%.*f", decimal_precision, *v);
5441  bool value_changed = false;
5443  if (ImGui::InputText("", buf, IM_ARRAYSIZE(buf), flags))
5444  {
5445  ApplyNumericalTextInput(buf, v);
5446  value_changed = true;
5447  }
5448 
5449  // Step buttons
5450  if (step > 0.0f)
5451  {
5453  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
5454  if (ImGui::Button("-", ImVec2(button_sz,button_sz), true))
5455  {
5456  *v -= g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
5457  value_changed = true;
5458  }
5459  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
5460  if (ImGui::Button("+", ImVec2(button_sz,button_sz), true))
5461  {
5462  *v += g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
5463  value_changed = true;
5464  }
5465  }
5466 
5467  ImGui::PopID();
5468 
5469  if (label_size.x > 0)
5470  {
5471  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
5472  ItemSize(label_size);
5473  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
5474  }
5475 
5476  return value_changed;
5477 }
5478 
5479 bool ImGui::InputInt(const char* label, int *v, int step, int step_fast, ImGuiInputTextFlags extra_flags)
5480 {
5481  float f = (float)*v;
5482  const bool value_changed = ImGui::InputFloat(label, &f, (float)step, (float)step_fast, 0, extra_flags);
5483  if (value_changed)
5484  *v = (int)f;
5485  return value_changed;
5486 }
5487 
5488 // Public API to manipulate UTF-8 text
5489 // We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
5490 void ImGuiTextEditCallbackData::DeleteChars(int pos, int bytes_count)
5491 {
5492  char* dst = Buf + pos;
5493  const char* src = Buf + pos + bytes_count;
5494  while (char c = *src++)
5495  *dst++ = c;
5496  *dst = '\0';
5497 
5498  BufDirty = true;
5499  if (CursorPos + bytes_count >= pos)
5500  CursorPos -= bytes_count;
5501  else if (CursorPos >= pos)
5502  CursorPos = pos;
5503  SelectionStart = SelectionEnd = CursorPos;
5504 }
5505 
5506 void ImGuiTextEditCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
5507 {
5508  const size_t text_len = strlen(Buf);
5509  if (!new_text_end)
5510  new_text_end = new_text + strlen(new_text);
5511  const size_t new_text_len = (size_t)(new_text_end - new_text);
5512 
5513  if (new_text_len + text_len + 1 >= BufSize)
5514  return;
5515 
5516  size_t upos = (size_t)pos;
5517  if (text_len != upos)
5518  memmove(Buf + upos + new_text_len, Buf + upos, text_len - upos);
5519  memcpy(Buf + upos, new_text, new_text_len * sizeof(char));
5520  Buf[text_len + new_text_len] = '\0';
5521 
5522  BufDirty = true;
5523  if (CursorPos >= pos)
5524  CursorPos += (int)new_text_len;
5525  SelectionStart = SelectionEnd = CursorPos;
5526 }
5527 
5528 // Return false to discard a character.
5529 static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
5530 {
5531  unsigned int c = *p_char;
5532 
5533  if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF)))
5534  return false;
5535 
5536  if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys.
5537  return false;
5538 
5540  {
5542  if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
5543  return false;
5544 
5546  if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
5547  return false;
5548 
5550  if (c >= 'a' && c <= 'z')
5551  *p_char = (c += (unsigned int)('A'-'a'));
5552 
5554  if (ImCharIsSpace(c))
5555  return false;
5556  }
5557 
5559  {
5560  ImGuiTextEditCallbackData callback_data;
5561  memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData));
5563  callback_data.EventChar = (ImWchar)c;
5564  callback_data.Flags = flags;
5565  callback_data.UserData = user_data;
5566  if (callback(&callback_data) != 0)
5567  return false;
5568  *p_char = callback_data.EventChar;
5569  if (!callback_data.EventChar)
5570  return false;
5571  }
5572 
5573  return true;
5574 }
5575 
5576 // Edit a string of text
5577 bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
5578 {
5579  ImGuiState& g = *GImGui;
5580  ImGuiWindow* window = GetCurrentWindow();
5581  if (window->SkipItems)
5582  return false;
5583 
5584  const ImGuiIO& io = g.IO;
5585  const ImGuiStyle& style = g.Style;
5586 
5587  const ImGuiID id = window->GetID(label);
5588  const float w = ImGui::CalcItemWidth();
5589 
5590  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5591  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
5592  const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
5593  ItemSize(bb);
5594  if (!ItemAdd(frame_bb, &id))
5595  return false;
5596 
5597  // NB: we are only allowed to access 'edit_state' if we are the active widget.
5598  ImGuiTextEditState& edit_state = g.InputTextState;
5599 
5600  const bool is_ctrl_down = io.KeyCtrl;
5601  const bool is_shift_down = io.KeyShift;
5602  const bool focus_requested = window->FocusItemRegister(g.ActiveId == id, (flags & ImGuiInputTextFlags_CallbackCompletion) == 0); // Using completion callback disable keyboard tabbing
5603  const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
5604  const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
5605 
5606  const bool hovered = IsHovered(frame_bb, id);
5607  if (hovered)
5608  g.HoveredId = id;
5609  const bool user_clicked = hovered && io.MouseClicked[0];
5610 
5611  bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0;
5612  if (focus_requested || user_clicked)
5613  {
5614  if (g.ActiveId != id)
5615  {
5616  // Start edition
5617  // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
5618  // From the moment we focused we are ignoring the content of 'buf'
5619  ImFormatString(edit_state.InitialText, IM_ARRAYSIZE(edit_state.InitialText), "%s", buf);
5620  const char* buf_end = NULL;
5621  edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), buf, NULL, &buf_end);
5622  edit_state.CurLenA = buf_end - buf; // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
5623  edit_state.Width = w;
5624  edit_state.InputCursorScreenPos = ImVec2(-1.f,-1.f);
5625  edit_state.CursorAnimReset();
5626 
5627  if (edit_state.Id != id)
5628  {
5629  edit_state.Id = id;
5630  edit_state.ScrollX = 0.0f;
5631  stb_textedit_initialize_state(&edit_state.StbState, true);
5632  if (focus_requested_by_code)
5633  select_all = true;
5634  }
5635  else
5636  {
5637  // Recycle existing cursor/selection/undo stack but clamp position
5638  // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
5639  edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, (int)edit_state.CurLenW);
5640  edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, (int)edit_state.CurLenW);
5641  edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, (int)edit_state.CurLenW);
5642  }
5643  if (focus_requested_by_tab || (user_clicked && is_ctrl_down))
5644  select_all = true;
5645  }
5646  SetActiveId(id);
5647  FocusWindow(window);
5648  }
5649  else if (io.MouseClicked[0])
5650  {
5651  // Release focus when we click outside
5652  if (g.ActiveId == id)
5653  {
5654  SetActiveId(0);
5655  }
5656  }
5657 
5658  // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
5659  // Down the line we should have a cleaner concept of focused vs active in the library.
5660  if (g.ActiveId == id)
5661  g.ActiveIdIsFocusedOnly = !io.MouseDown[0];
5662 
5663  bool value_changed = false;
5664  bool cancel_edit = false;
5665  bool enter_pressed = false;
5666  static char text_tmp_utf8[IM_ARRAYSIZE(edit_state.InitialText)];
5667  if (g.ActiveId == id)
5668  {
5669  // Edit in progress
5670  edit_state.BufSizeA = buf_size;
5671  edit_state.Font = window->Font();
5672  edit_state.FontSize = window->FontSize();
5673 
5674  const float mx = g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x;
5675  const float my = window->FontSize()*0.5f; // Flatten mouse because we are doing a single-line edit
5676 
5677  edit_state.UpdateScrollOffset();
5678  if (select_all || (hovered && io.MouseDoubleClicked[0]))
5679  {
5680  edit_state.SelectAll();
5681  edit_state.SelectedAllMouseLock = true;
5682  }
5683  else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)
5684  {
5685  stb_textedit_click(&edit_state, &edit_state.StbState, mx + edit_state.ScrollX, my);
5686  edit_state.CursorAnimReset();
5687 
5688  }
5689  else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock)
5690  {
5691  stb_textedit_drag(&edit_state, &edit_state.StbState, mx + edit_state.ScrollX, my);
5692  edit_state.CursorAnimReset();
5693  }
5694  if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
5695  edit_state.SelectedAllMouseLock = false;
5696 
5697  if (g.IO.InputCharacters[0])
5698  {
5699  // Process text input (before we check for Return because using some IME will effectively send a Return?)
5700  for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
5701  {
5702  unsigned int c = (unsigned int)g.IO.InputCharacters[n];
5703  if (c)
5704  {
5705  // Insert character if they pass filtering
5706  if (!InputTextFilterCharacter(&c, flags, callback, user_data))
5707  continue;
5708  edit_state.OnKeyPressed((int)c);
5709  }
5710  }
5711 
5712  // Consume characters
5713  memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
5714  }
5715 
5716  const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0);
5717  if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
5718  else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); }
5719  else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
5720  else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
5721  else if (IsKeyPressedMap(ImGuiKey_Delete)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
5722  else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
5723  else if (IsKeyPressedMap(ImGuiKey_Enter)) { SetActiveId(0); enter_pressed = true; }
5724  else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveId(0); cancel_edit = true; }
5725  else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); }
5726  else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); }
5727  else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); }
5728  else if (is_ctrl_down && (IsKeyPressedMap(ImGuiKey_X) || IsKeyPressedMap(ImGuiKey_C)))
5729  {
5730  // Cut, Copy
5731  const bool cut = IsKeyPressedMap(ImGuiKey_X);
5732  if (cut && !edit_state.HasSelection())
5733  edit_state.SelectAll();
5734 
5735  if (g.IO.SetClipboardTextFn)
5736  {
5737  const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
5738  const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)edit_state.CurLenW;
5739  ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie);
5740  g.IO.SetClipboardTextFn(text_tmp_utf8);
5741  }
5742 
5743  if (cut)
5744  stb_textedit_cut(&edit_state, &edit_state.StbState);
5745  }
5746  else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_V))
5747  {
5748  // Paste
5749  if (g.IO.GetClipboardTextFn)
5750  {
5751  if (const char* clipboard = g.IO.GetClipboardTextFn())
5752  {
5753  // Remove new-line from pasted buffer
5754  const size_t clipboard_len = strlen(clipboard);
5755  ImWchar* clipboard_filtered = (ImWchar*)ImGui::MemAlloc((clipboard_len+1) * sizeof(ImWchar));
5756  int clipboard_filtered_len = 0;
5757  for (const char* s = clipboard; *s; )
5758  {
5759  unsigned int c;
5760  s += ImTextCharFromUtf8(&c, s, NULL);
5761  if (c == 0)
5762  break;
5763  if (c >= 0x10000)
5764  continue;
5765  if (!InputTextFilterCharacter(&c, flags, callback, user_data))
5766  continue;
5767  clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
5768  }
5769  clipboard_filtered[clipboard_filtered_len] = 0;
5770  if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
5771  stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
5772  ImGui::MemFree(clipboard_filtered);
5773  }
5774  }
5775  }
5776 
5777  edit_state.CursorAnim += g.IO.DeltaTime;
5778  edit_state.UpdateScrollOffset();
5779 
5780  if (cancel_edit)
5781  {
5782  // Restore initial value
5783  ImFormatString(buf, buf_size, "%s", edit_state.InitialText);
5784  value_changed = true;
5785  }
5786  else
5787  {
5788  // Apply new value immediately - copy modified buffer back
5789  // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
5790  // FIXME: We actually always render 'buf' in RenderTextScrolledClipped
5791  // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
5792  ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text, NULL);
5793 
5794  // User callback
5795  if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0)
5796  {
5797  IM_ASSERT(callback != NULL);
5798 
5799  // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
5800  ImGuiInputTextFlags event_flag = 0;
5801  ImGuiKey event_key = ImGuiKey_COUNT;
5802  if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))
5803  {
5805  event_key = ImGuiKey_Tab;
5806  }
5808  {
5810  event_key = ImGuiKey_UpArrow;
5811  }
5812  else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))
5813  {
5815  event_key = ImGuiKey_DownArrow;
5816  }
5817 
5818  if (event_key != ImGuiKey_COUNT || (flags & ImGuiInputTextFlags_CallbackAlways) != 0)
5819  {
5820  ImGuiTextEditCallbackData callback_data;
5821  callback_data.EventFlag = event_flag;
5822  callback_data.EventKey = event_key;
5823  callback_data.Buf = text_tmp_utf8;
5824  callback_data.BufSize = edit_state.BufSizeA;
5825  callback_data.BufDirty = false;
5826  callback_data.Flags = flags;
5827  callback_data.UserData = user_data;
5828 
5829  // We have to convert from position from wchar to UTF-8 positions
5830  const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.cursor);
5831  const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.select_start);
5832  const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(edit_state.Text, edit_state.Text + edit_state.StbState.select_end);
5833 
5834  // Call user code
5835  callback(&callback_data);
5836 
5837  // Read back what user may have modified
5838  IM_ASSERT(callback_data.Buf == text_tmp_utf8); // Invalid to modify those fields
5839  IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA);
5840  IM_ASSERT(callback_data.Flags == flags);
5841  if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos);
5842  if (callback_data.SelectionStart != utf8_selection_start) edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart);
5843  if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);
5844  if (callback_data.BufDirty)
5845  {
5846  ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), text_tmp_utf8, NULL);
5847  edit_state.CursorAnimReset();
5848  }
5849  }
5850  }
5851 
5852  if (strcmp(text_tmp_utf8, buf) != 0)
5853  {
5854  ImFormatString(buf, buf_size, "%s", text_tmp_utf8);
5855  value_changed = true;
5856  }
5857  }
5858  }
5859 
5860  RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
5861 
5862  const ImVec2 font_off_up = ImVec2(0.0f,window->FontSize()+1.0f); // FIXME: those offsets are part of the style or font API
5863  const ImVec2 font_off_dn = ImVec2(0.0f,2.0f);
5864 
5865  if (g.ActiveId == id)
5866  {
5867  // Draw selection
5868  const int select_begin_idx = edit_state.StbState.select_start;
5869  const int select_end_idx = edit_state.StbState.select_end;
5870  if (select_begin_idx != select_end_idx)
5871  {
5872  const ImVec2 select_begin_pos = frame_bb.Min + style.FramePadding + edit_state.CalcDisplayOffsetFromCharIdx(ImMin(select_begin_idx,select_end_idx));
5873  const ImVec2 select_end_pos = frame_bb.Min + style.FramePadding + edit_state.CalcDisplayOffsetFromCharIdx(ImMax(select_begin_idx,select_end_idx));
5874  window->DrawList->AddRectFilled(select_begin_pos - font_off_up, select_end_pos + font_off_dn, window->Color(ImGuiCol_TextSelectedBg));
5875  }
5876  }
5877 
5878  ImGuiTextEditState::RenderTextScrolledClipped(window->Font(), window->FontSize(), buf, frame_bb.Min + style.FramePadding, w, (g.ActiveId == id) ? edit_state.ScrollX : 0.0f);
5879 
5880  if (g.ActiveId == id)
5881  {
5882  const ImVec2 cursor_pos = frame_bb.Min + style.FramePadding + edit_state.CalcDisplayOffsetFromCharIdx(edit_state.StbState.cursor);
5883 
5884  // Draw blinking cursor
5885  if (g.InputTextState.CursorIsVisible())
5886  window->DrawList->AddRect(cursor_pos - font_off_up + ImVec2(0,2), cursor_pos + font_off_dn - ImVec2(0,3), window->Color(ImGuiCol_Text));
5887 
5888  // Notify OS of text input position for advanced IME
5889  if (io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_pos) > 0.0001f)
5890  io.ImeSetInputScreenPosFn((int)cursor_pos.x - 1, (int)(cursor_pos.y - window->FontSize())); // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
5891 
5892  edit_state.InputCursorScreenPos = cursor_pos;
5893  }
5894 
5895  if (label_size.x > 0)
5896  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
5897 
5898  if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
5899  return enter_pressed;
5900  else
5901  return value_changed;
5902 }
5903 
5904 static bool InputFloatN(const char* label, float* v, int components, int decimal_precision)
5905 {
5906  ImGuiState& g = *GImGui;
5907  ImGuiWindow* window = GetCurrentWindow();
5908  if (window->SkipItems)
5909  return false;
5910 
5911  const ImGuiStyle& style = g.Style;
5912  const float w_full = ImGui::CalcItemWidth();
5913  const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components));
5914  const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)));
5915 
5916  bool value_changed = false;
5917  ImGui::PushID(label);
5918  ImGui::PushItemWidth(w_item_one);
5919  for (int i = 0; i < components; i++)
5920  {
5921  ImGui::PushID(i);
5922  if (i + 1 == components)
5923  {
5925  ImGui::PushItemWidth(w_item_last);
5926  }
5927  value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision);
5928  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
5929  ImGui::PopID();
5930  }
5932  ImGui::PopID();
5933 
5935 
5936  return value_changed;
5937 }
5938 
5939 bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision)
5940 {
5941  return InputFloatN(label, v, 2, decimal_precision);
5942 }
5943 
5944 bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision)
5945 {
5946  return InputFloatN(label, v, 3, decimal_precision);
5947 }
5948 
5949 bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision)
5950 {
5951  return InputFloatN(label, v, 4, decimal_precision);
5952 }
5953 
5954 static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
5955 {
5956  const char** items = (const char**)data;
5957  if (out_text)
5958  *out_text = items[idx];
5959  return true;
5960 }
5961 
5962 static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
5963 {
5964  // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
5965  const char* items_separated_by_zeros = (const char*)data;
5966  int items_count = 0;
5967  const char* p = items_separated_by_zeros;
5968  while (*p)
5969  {
5970  if (idx == items_count)
5971  break;
5972  p += strlen(p) + 1;
5973  items_count++;
5974  }
5975  if (!*p)
5976  return false;
5977  if (out_text)
5978  *out_text = p;
5979  return true;
5980 }
5981 
5982 // Combo box helper allowing to pass an array of strings.
5983 bool ImGui::Combo(const char* label, int* current_item, const char** items, int items_count, int height_in_items)
5984 {
5985  const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
5986  return value_changed;
5987 }
5988 
5989 // Combo box helper allowing to pass all items in a single string.
5990 bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
5991 {
5992  int items_count = 0;
5993  const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this
5994  while (*p)
5995  {
5996  p += strlen(p) + 1;
5997  items_count++;
5998  }
5999  bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
6000  return value_changed;
6001 }
6002 
6003 // Combo box function.
6004 bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
6005 {
6006  ImGuiState& g = *GImGui;
6007  ImGuiWindow* window = GetCurrentWindow();
6008  if (window->SkipItems)
6009  return false;
6010 
6011  const ImGuiStyle& style = g.Style;
6012  const ImGuiID id = window->GetID(label);
6013  const float w = ImGui::CalcItemWidth();
6014 
6015  const ImVec2 label_size = CalcTextSize(label, NULL, true);
6016  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
6017  const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(style.ItemInnerSpacing.x + label_size.x,0));
6018  ItemSize(bb);
6019  if (!ItemAdd(frame_bb, &id))
6020  return false;
6021 
6022  const float arrow_size = (window->FontSize() + style.FramePadding.x * 2.0f);
6023  const bool hovered = IsHovered(frame_bb, id);
6024 
6025  bool value_changed = false;
6026  const ImGuiAabb value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
6027  RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding);
6028  RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, window->Color(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING
6029  RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true);
6030 
6031  if (*current_item >= 0 && *current_item < items_count)
6032  {
6033  const char* item_text;
6034  if (items_getter(data, *current_item, &item_text))
6035  RenderTextClipped(frame_bb.Min + style.FramePadding, item_text, NULL, NULL, value_bb.Max);
6036  }
6037 
6038  if (label_size.x > 0)
6039  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
6040 
6041  ImGui::PushID((int)id);
6042  bool menu_toggled = false;
6043  if (hovered)
6044  {
6045  g.HoveredId = id;
6046  if (g.IO.MouseClicked[0])
6047  {
6048  menu_toggled = true;
6049  g.ActiveComboID = (g.ActiveComboID == id) ? 0 : id;
6050  if (g.ActiveComboID)
6051  FocusWindow(window);
6052  }
6053  }
6054 
6055  if (g.ActiveComboID == id)
6056  {
6057  // Size default to hold ~7 items
6058  if (height_in_items < 0)
6059  height_in_items = 7;
6060 
6061  const ImVec2 backup_pos = ImGui::GetCursorPos();
6062  const float popup_off_x = 0.0f;//style.ItemInnerSpacing.x;
6063  const float popup_height = (label_size.y + style.ItemSpacing.y) * ImMin(items_count, height_in_items) + style.WindowPadding.y;
6064  const ImGuiAabb popup_aabb(ImVec2(frame_bb.Min.x+popup_off_x, frame_bb.Max.y), ImVec2(frame_bb.Max.x+popup_off_x, frame_bb.Max.y + popup_height));
6065  ImGui::SetCursorPos(popup_aabb.Min - window->Pos);
6066 
6068  ImGui::BeginChild("#ComboBox", popup_aabb.GetSize(), false, flags);
6069  ImGui::Spacing();
6070 
6071  bool combo_item_active = false;
6072  combo_item_active |= (g.ActiveId == GetCurrentWindow()->GetID("#SCROLLY"));
6073 
6074  // Display items
6075  for (int i = 0; i < items_count; i++)
6076  {
6077  ImGui::PushID((void*)(intptr_t)i);
6078  const bool item_selected = (i == *current_item);
6079  const char* item_text;
6080  if (!items_getter(data, i, &item_text))
6081  item_text = "*Unknown item*";
6082  if (ImGui::Selectable(item_text, item_selected))
6083  {
6084  SetActiveId(0);
6085  g.ActiveComboID = 0;
6086  value_changed = true;
6087  *current_item = i;
6088  }
6089  if (item_selected && menu_toggled)
6091  combo_item_active |= ImGui::IsItemActive();
6092  ImGui::PopID();
6093  }
6094  ImGui::EndChild();
6095  ImGui::SetCursorPos(backup_pos);
6096 
6097  if (!combo_item_active && g.ActiveId != 0)
6098  g.ActiveComboID = 0;
6099  }
6100 
6101  ImGui::PopID();
6102 
6103  return value_changed;
6104 }
6105 
6106 // Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image.
6107 // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID.
6108 bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg)
6109 {
6110  ImGuiState& g = *GImGui;
6111  ImGuiWindow* window = GetCurrentWindow();
6112  if (window->SkipItems)
6113  return false;
6114 
6115  const ImGuiStyle& style = g.Style;
6116  const ImGuiID id = window->GetID(label);
6117  const ImVec2 label_size = CalcTextSize(label, NULL, true);
6118 
6119  const float w = window->Pos.x + ImGui::GetContentRegionMax().x - window->DC.CursorPos.x;
6120  const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : w, size_arg.y != 0.0f ? size_arg.y : label_size.y);
6121  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + size);
6122  ItemSize(bb);
6123 
6124  // Selectables are meant to be tightly packed together. So for both rendering and collision we extend to compensate for spacing.
6125  ImGuiAabb bb_with_spacing = bb;
6126  const float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f);
6127  const float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f);
6128  const float spacing_R = style.ItemSpacing.x - spacing_L;
6129  const float spacing_D = style.ItemSpacing.y - spacing_U;
6130  bb_with_spacing.Min.x -= spacing_L;
6131  bb_with_spacing.Min.y -= spacing_U;
6132  bb_with_spacing.Max.x += spacing_R;
6133  bb_with_spacing.Max.y += spacing_D;
6134  if (!ItemAdd(bb_with_spacing, &id))
6135  return false;
6136 
6137  bool hovered, held;
6138  bool pressed = ButtonBehaviour(bb_with_spacing, id, &hovered, &held, true, false, false);
6139 
6140  // Render
6141  if (hovered || selected)
6142  {
6143  const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
6144  RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, style.FrameRounding);
6145  }
6146 
6147  //const ImVec2 off = ImVec2(ImMax(0.0f, size.x - text_size.x) * 0.5f, ImMax(0.0f, size.y - text_size.y) * 0.5f);
6148  RenderTextClipped(bb.Min, label, NULL, &label_size, bb_with_spacing.Max);
6149 
6150  return pressed;
6151 }
6152 
6153 bool ImGui::Selectable(const char* label, bool* p_selected, const ImVec2& size_arg)
6154 {
6155  if (ImGui::Selectable(label, *p_selected, size_arg))
6156  {
6157  *p_selected = !*p_selected;
6158  return true;
6159  }
6160  return false;
6161 }
6162 
6163 // Helper to calculate the size of a listbox and display a label on the right.
6164 // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty"
6165 bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
6166 {
6167  ImGuiWindow* window = GetCurrentWindow();
6168 
6169  const ImGuiStyle& style = ImGui::GetStyle();
6170  const ImGuiID id = ImGui::GetID(label);
6171  const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
6172 
6173  // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
6174  ImVec2 size;
6175  size.x = (size_arg.x != 0.0f) ? size_arg.x : ImGui::CalcItemWidth() + style.FramePadding.x * 2.0f;
6176  size.y = (size_arg.y != 0.0f) ? size_arg.y : ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y;
6177  const ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
6178  const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
6179  const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
6180  window->DC.LastItemAabb = bb;
6181 
6182  if (label_size.x > 0)
6183  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
6184 
6185  ImGui::BeginChildFrame(id, frame_bb.GetSize());
6186  return true;
6187 }
6188 
6189 bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
6190 {
6191  // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
6192  // However we don't add +0.40f if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size.
6193  // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution.
6194  if (height_in_items < 0)
6195  height_in_items = ImMin(items_count, 7);
6196  float height_in_items_f = height_in_items < items_count ? (height_in_items + 0.40f) : (height_in_items + 0.00f);
6197 
6198  // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().
6199  ImVec2 size;
6200  size.x = 0.0f;
6201  size.y = ImGui::GetTextLineHeightWithSpacing() * height_in_items_f + ImGui::GetStyle().ItemSpacing.y;
6202  return ImGui::ListBoxHeader(label, size);
6203 }
6204 
6206 {
6207  ImGuiWindow* parent_window = GetParentWindow();
6208  const ImGuiAabb bb = parent_window->DC.LastItemAabb;
6209 
6211 
6212  parent_window->DC.CursorPos = bb.Min;
6213  ItemSize(bb, NULL);
6214 }
6215 
6216 bool ImGui::ListBox(const char* label, int* current_item, const char** items, int items_count, int height_items)
6217 {
6218  const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
6219  return value_changed;
6220 }
6221 
6222 bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
6223 {
6224  ImGuiWindow* window = GetCurrentWindow();
6225  if (window->SkipItems)
6226  return false;
6227 
6228  if (!ImGui::ListBoxHeader(label, items_count, height_in_items))
6229  return false;
6230 
6231  bool value_changed = false;
6232  for (int i = 0; i < items_count; i++)
6233  {
6234  const bool item_selected = (i == *current_item);
6235  const char* item_text;
6236  if (!items_getter(data, i, &item_text))
6237  item_text = "*Unknown item*";
6238 
6239  ImGui::PushID(i);
6240  if (ImGui::Selectable(item_text, item_selected))
6241  {
6242  *current_item = i;
6243  value_changed = true;
6244  }
6245  ImGui::PopID();
6246  }
6247 
6249  return value_changed;
6250 }
6251 
6252 // A little colored square. Return true when clicked.
6253 bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_border)
6254 {
6255  ImGuiState& g = *GImGui;
6256  ImGuiWindow* window = GetCurrentWindow();
6257  if (window->SkipItems)
6258  return false;
6259 
6260  const ImGuiStyle& style = g.Style;
6261  const ImGuiID id = window->GetID("#colorbutton");
6262  const float square_size = window->FontSize();
6263  const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(square_size + style.FramePadding.x*2, square_size + (small_height ? 0 : style.FramePadding.y*2)));
6264  ItemSize(bb);
6265  if (!ItemAdd(bb, &id))
6266  return false;
6267 
6268  bool hovered, held;
6269  bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true);
6270  RenderFrame(bb.Min, bb.Max, window->Color(col), outline_border, style.FrameRounding);
6271 
6272  if (hovered)
6273  {
6274  int ix = (int)(col.x * 255.0f + 0.5f);
6275  int iy = (int)(col.y * 255.0f + 0.5f);
6276  int iz = (int)(col.z * 255.0f + 0.5f);
6277  int iw = (int)(col.w * 255.0f + 0.5f);
6278  ImGui::SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, ix, iy, iz, iw);
6279  }
6280 
6281  return pressed;
6282 }
6283 
6284 bool ImGui::ColorEdit3(const char* label, float col[3])
6285 {
6286  float col4[4];
6287  col4[0] = col[0];
6288  col4[1] = col[1];
6289  col4[2] = col[2];
6290  col4[3] = 1.0f;
6291  const bool value_changed = ImGui::ColorEdit4(label, col4, false);
6292  col[0] = col4[0];
6293  col[1] = col4[1];
6294  col[2] = col4[2];
6295  return value_changed;
6296 }
6297 
6298 // Edit colors components (each component in 0.0f..1.0f range
6299 // Use CTRL-Click to input value and TAB to go to next item.
6300 bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
6301 {
6302  ImGuiState& g = *GImGui;
6303  ImGuiWindow* window = GetCurrentWindow();
6304  if (window->SkipItems)
6305  return false;
6306 
6307  const ImGuiStyle& style = g.Style;
6308  const ImGuiID id = window->GetID(label);
6309  const float w_full = ImGui::CalcItemWidth();
6310  const float square_sz = (window->FontSize() + style.FramePadding.x * 2.0f);
6311 
6312  ImGuiColorEditMode edit_mode = window->DC.ColorEditMode;
6314  edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3;
6315 
6316  float fx = col[0];
6317  float fy = col[1];
6318  float fz = col[2];
6319  float fw = col[3];
6320  const ImVec4 col_display(fx, fy, fz, 1.0f);
6321 
6322  if (edit_mode == ImGuiColorEditMode_HSV)
6323  ImGui::ColorConvertRGBtoHSV(fx, fy, fz, fx, fy, fz);
6324 
6325  int ix = (int)(fx * 255.0f + 0.5f);
6326  int iy = (int)(fy * 255.0f + 0.5f);
6327  int iz = (int)(fz * 255.0f + 0.5f);
6328  int iw = (int)(fw * 255.0f + 0.5f);
6329 
6330  int components = alpha ? 4 : 3;
6331  bool value_changed = false;
6332 
6333  ImGui::PushID(label);
6334 
6335  bool hsv = (edit_mode == 1);
6336  switch (edit_mode)
6337  {
6340  {
6341  // 0: RGB 0..255 Sliders
6342  // 1: HSV 0..255 Sliders
6343  const float w_items_all = w_full - (square_sz + style.ItemInnerSpacing.x);
6344  const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components));
6345  const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)));
6346 
6347  ImGui::PushItemWidth(w_item_one);
6348  value_changed |= ImGui::SliderInt("##X", &ix, 0, 255, hsv ? "H:%3.0f" : "R:%3.0f");
6349  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6350  value_changed |= ImGui::SliderInt("##Y", &iy, 0, 255, hsv ? "S:%3.0f" : "G:%3.0f");
6351  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6352  if (alpha)
6353  {
6354  value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hsv ? "V:%3.0f" : "B:%3.0f");
6355  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6356  ImGui::PushItemWidth(w_item_last);
6357  value_changed |= ImGui::SliderInt("##W", &iw, 0, 255, "A:%3.0f");
6358  }
6359  else
6360  {
6361  ImGui::PushItemWidth(w_item_last);
6362  value_changed |= ImGui::SliderInt("##Z", &iz, 0, 255, hsv ? "V:%3.0f" : "B:%3.0f");
6363  }
6366  }
6367  break;
6369  {
6370  // 2: RGB Hexadecimal
6371  const float w_slider_all = w_full - square_sz;
6372  char buf[64];
6373  if (alpha)
6374  sprintf(buf, "#%02X%02X%02X%02X", ix, iy, iz, iw);
6375  else
6376  sprintf(buf, "#%02X%02X%02X", ix, iy, iz);
6377  ImGui::PushItemWidth(w_slider_all - style.ItemInnerSpacing.x);
6378  value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal);
6380  char* p = buf;
6381  while (*p == '#' || ImCharIsSpace(*p))
6382  p++;
6383 
6384  // Treat at unsigned (%X is unsigned)
6385  ix = iy = iz = iw = 0;
6386  if (alpha)
6387  sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&ix, (unsigned int*)&iy, (unsigned int*)&iz, (unsigned int*)&iw);
6388  else
6389  sscanf(p, "%02X%02X%02X", (unsigned int*)&ix, (unsigned int*)&iy, (unsigned int*)&iz);
6390  }
6391  break;
6392  }
6393 
6394  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6395  if (ImGui::ColorButton(col_display))
6396  {
6397  // Don't set local copy of 'edit_mode' right away!
6398  g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3);
6399  }
6400 
6401  if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton)
6402  {
6403  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6404  const char* button_titles[3] = { "RGB", "HSV", "HEX" };
6405  if (ImGui::Button(button_titles[edit_mode]))
6406  {
6407  // Don't set local copy of 'edit_mode' right away!
6408  g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3);
6409  }
6410  ImGui::SameLine();
6411  }
6412  else
6413  {
6414  ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
6415  }
6416 
6418 
6419  // Convert back
6420  fx = ix / 255.0f;
6421  fy = iy / 255.0f;
6422  fz = iz / 255.0f;
6423  fw = iw / 255.0f;
6424  if (edit_mode == 1)
6425  ImGui::ColorConvertHSVtoRGB(fx, fy, fz, fx, fy, fz);
6426 
6427  if (value_changed)
6428  {
6429  col[0] = fx;
6430  col[1] = fy;
6431  col[2] = fz;
6432  if (alpha)
6433  col[3] = fw;
6434  }
6435 
6436  ImGui::PopID();
6437 
6438  return value_changed;
6439 }
6440 
6442 {
6443  ImGuiWindow* window = GetCurrentWindow();
6444  window->DC.ColorEditMode = mode;
6445 }
6446 
6447 // Horizontal separating line.
6449 {
6450  ImGuiWindow* window = GetCurrentWindow();
6451  if (window->SkipItems)
6452  return;
6453 
6454  if (window->DC.ColumnsCount > 1)
6455  PopClipRect();
6456 
6457  const ImGuiAabb bb(ImVec2(window->Pos.x, window->DC.CursorPos.y), ImVec2(window->Pos.x + window->Size.x, window->DC.CursorPos.y));
6458  ItemSize(ImVec2(0.0f, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
6459  if (!ItemAdd(bb, NULL))
6460  {
6461  if (window->DC.ColumnsCount > 1)
6463  return;
6464  }
6465 
6466  window->DrawList->AddLine(bb.Min, bb.Max, window->Color(ImGuiCol_Border));
6467 
6468  if (window->DC.ColumnsCount > 1)
6469  {
6471  window->DC.ColumnsCellMinY = window->DC.CursorPos.y;
6472  }
6473 }
6474 
6475 // A little vertical spacing.
6477 {
6478  ImGuiWindow* window = GetCurrentWindow();
6479  if (window->SkipItems)
6480  return;
6481 
6482  ItemSize(ImVec2(0,0));
6483 }
6484 
6485 // Advance cursor given item size.
6486 static void ItemSize(ImVec2 size, ImVec2* adjust_vertical_offset)
6487 {
6488  ImGuiState& g = *GImGui;
6489  ImGuiWindow* window = GetCurrentWindow();
6490  if (window->SkipItems)
6491  return;
6492 
6493  const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
6494  if (adjust_vertical_offset)
6495  adjust_vertical_offset->y = adjust_vertical_offset->y + (line_height - size.y) * 0.5f;
6496 
6497  // Always align ourselves on pixel boundaries
6498  window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
6499  window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));
6500 
6501  window->SizeContentsCurrent = ImMax(window->SizeContentsCurrent, ImVec2(window->DC.CursorPosPrevLine.x - window->Pos.x, window->DC.CursorPos.y + window->ScrollY - window->Pos.y));
6502 
6503  window->DC.PrevLineHeight = line_height;
6504  window->DC.CurrentLineHeight = 0.0f;
6505 }
6506 
6507 static void ItemSize(const ImGuiAabb& bb, ImVec2* adjust_start_offset)
6508 {
6509  ItemSize(bb.GetSize(), adjust_start_offset);
6510 }
6511 
6512 static bool IsClipped(const ImGuiAabb& bb)
6513 {
6514  ImGuiState& g = *GImGui;
6515  ImGuiWindow* window = GetCurrentWindow();
6516 
6517  if (!bb.Overlaps(ImGuiAabb(window->ClipRectStack.back())) && !g.LogEnabled)
6518  return true;
6519  return false;
6520 }
6521 
6522 bool ImGui::IsClipped(const ImVec2& item_size)
6523 {
6524  ImGuiWindow* window = GetCurrentWindow();
6525  return IsClipped(ImGuiAabb(window->DC.CursorPos, window->DC.CursorPos + item_size));
6526 }
6527 
6528 static bool ItemAdd(const ImGuiAabb& bb, const ImGuiID* id)
6529 {
6530  ImGuiWindow* window = GetCurrentWindow();
6531  window->DC.LastItemID = id ? *id : 0;
6532  window->DC.LastItemAabb = bb;
6533  if (IsClipped(bb))
6534  {
6535  window->DC.LastItemHovered = false;
6536  return false;
6537  }
6538 
6539  // This is a sensible default, but widgets are free to override it after calling ItemAdd()
6540  const bool hovered = IsMouseHoveringBox(bb);
6541  //const bool hovered = (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly) && IsMouseHoveringBox(bb); // matching the behaviour of IsHovered(), not always what the user wants?
6542  window->DC.LastItemHovered = hovered;
6543  return true;
6544 }
6545 
6546 // Gets back to previous line and continue with horizontal layout
6547 // column_x == 0 : follow on previous item
6548 // columm_x != 0 : align to specified column
6549 // spacing_w < 0 : use default spacing if column_x==0, no spacing if column_x!=0
6550 // spacing_w >= 0 : enforce spacing
6551 void ImGui::SameLine(int column_x, int spacing_w)
6552 {
6553  ImGuiState& g = *GImGui;
6554  ImGuiWindow* window = GetCurrentWindow();
6555  if (window->SkipItems)
6556  return;
6557 
6558  float x, y;
6559  if (column_x != 0)
6560  {
6561  if (spacing_w < 0) spacing_w = 0;
6562  x = window->Pos.x + (float)column_x + (float)spacing_w;
6563  y = window->DC.CursorPosPrevLine.y;
6564  }
6565  else
6566  {
6567  if (spacing_w < 0) spacing_w = (int)g.Style.ItemSpacing.x;
6568  x = window->DC.CursorPosPrevLine.x + (float)spacing_w;
6569  y = window->DC.CursorPosPrevLine.y;
6570  }
6571  window->DC.CurrentLineHeight = window->DC.PrevLineHeight;
6572  window->DC.CursorPos = ImVec2(x, y);
6573 }
6574 
6576 {
6577  ImGuiState& g = *GImGui;
6578  ImGuiWindow* window = GetCurrentWindow();
6579  if (window->SkipItems)
6580  return;
6581 
6582  if (window->DC.ColumnsCount > 1)
6583  {
6585  PopClipRect();
6586 
6587  window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);
6588  if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount)
6589  {
6590  window->DC.ColumnsOffsetX = ImGui::GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.ColumnsStartX + g.Style.ItemSpacing.x;
6591  }
6592  else
6593  {
6594  window->DC.ColumnsCurrent = 0;
6595  window->DC.ColumnsOffsetX = 0.0f;
6596  window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY;
6597  }
6598  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX);
6599  window->DC.CursorPos.y = window->DC.ColumnsCellMinY;
6600  window->DC.CurrentLineHeight = 0.0f;
6601 
6604  }
6605 }
6606 
6608 {
6609  ImGuiWindow* window = GetCurrentWindow();
6610  return window->DC.ColumnsCurrent;
6611 }
6612 
6614 {
6615  ImGuiWindow* window = GetCurrentWindow();
6616  return window->DC.ColumnsCount;
6617 }
6618 
6619 float ImGui::GetColumnOffset(int column_index)
6620 {
6621  ImGuiState& g = *GImGui;
6622  ImGuiWindow* window = GetCurrentWindow();
6623  if (column_index < 0)
6624  column_index = window->DC.ColumnsCurrent;
6625 
6626  // Read from cache
6627  IM_ASSERT(column_index < (int)window->DC.ColumnsOffsetsT.size());
6628  const float t = window->DC.ColumnsOffsetsT[column_index];
6629 
6630  const float min_x = window->DC.ColumnsStartX;
6631  const float max_x = window->Size.x - (g.Style.ScrollbarWidth);// - window->WindowPadding().x;
6632  const float offset = min_x + t * (max_x - min_x);
6633  return offset;
6634 }
6635 
6636 void ImGui::SetColumnOffset(int column_index, float offset)
6637 {
6638  ImGuiState& g = *GImGui;
6639  ImGuiWindow* window = GetCurrentWindow();
6640  if (column_index < 0)
6641  column_index = window->DC.ColumnsCurrent;
6642 
6643  IM_ASSERT(column_index < (int)window->DC.ColumnsOffsetsT.size());
6644  const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(column_index);
6645 
6646  const float min_x = window->DC.ColumnsStartX;
6647  const float max_x = window->Size.x - (g.Style.ScrollbarWidth);// - window->WindowPadding().x;
6648  const float t = (offset - min_x) / (max_x - min_x);
6649  window->DC.StateStorage->SetFloat(column_id, t);
6650  window->DC.ColumnsOffsetsT[column_index] = t;
6651 }
6652 
6653 float ImGui::GetColumnWidth(int column_index)
6654 {
6655  ImGuiWindow* window = GetCurrentWindow();
6656  if (column_index < 0)
6657  column_index = window->DC.ColumnsCurrent;
6658 
6659  const float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index);
6660  return w;
6661 }
6662 
6663 static void PushColumnClipRect(int column_index)
6664 {
6665  ImGuiWindow* window = GetCurrentWindow();
6666  if (column_index < 0)
6667  column_index = window->DC.ColumnsCurrent;
6668 
6669  const float x1 = window->Pos.x + ImGui::GetColumnOffset(column_index) - 1;
6670  const float x2 = window->Pos.x + ImGui::GetColumnOffset(column_index+1) - 1;
6671  PushClipRect(ImVec4(x1,-FLT_MAX,x2,+FLT_MAX));
6672 }
6673 
6674 void ImGui::Columns(int columns_count, const char* id, bool border)
6675 {
6676  ImGuiState& g = *GImGui;
6677  ImGuiWindow* window = GetCurrentWindow();
6678 
6679  if (window->DC.ColumnsCount != 1)
6680  {
6681  if (window->DC.ColumnsCurrent != 0)
6682  ItemSize(ImVec2(0,0)); // Advance to column 0
6684  PopClipRect();
6685 
6686  window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);
6687  window->DC.CursorPos.y = window->DC.ColumnsCellMaxY;
6688  }
6689 
6690  // Draw columns borders and handle resize at the time of "closing" a columns set
6691  if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems)
6692  {
6693  const float y1 = window->DC.ColumnsStartPos.y;
6694  const float y2 = window->DC.CursorPos.y;
6695  for (int i = 1; i < window->DC.ColumnsCount; i++)
6696  {
6697  float x = window->Pos.x + GetColumnOffset(i);
6698 
6699  const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(i);
6700  const ImGuiAabb column_aabb(ImVec2(x-4,y1),ImVec2(x+4,y2));
6701 
6702  if (IsClipped(column_aabb))
6703  continue;
6704 
6705  bool hovered, held;
6706  ButtonBehaviour(column_aabb, column_id, &hovered, &held, true);
6707 
6708  // Draw before resize so our items positioning are in sync with the line being drawn
6709  const ImU32 col = window->Color(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column);
6710  const float xi = (float)(int)x;
6711  window->DrawList->AddLine(ImVec2(xi, y1), ImVec2(xi, y2), col);
6712 
6713  if (held)
6714  {
6715  x -= window->Pos.x;
6716  x = ImClamp(x + g.IO.MouseDelta.x, ImGui::GetColumnOffset(i-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(i+1)-g.Style.ColumnsMinSpacing);
6717  SetColumnOffset(i, x);
6718  x += window->Pos.x;
6719  }
6720  }
6721  }
6722 
6723  // Set state for first column
6724  window->DC.ColumnsSetID = window->GetID(id ? id : "");
6725  window->DC.ColumnsCurrent = 0;
6726  window->DC.ColumnsCount = columns_count;
6727  window->DC.ColumnsShowBorders = border;
6728  window->DC.ColumnsStartPos = window->DC.CursorPos;
6729  window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y;
6730  window->DC.ColumnsOffsetX = 0.0f;
6731  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX);
6732 
6733  if (window->DC.ColumnsCount != 1)
6734  {
6735  // Cache column offsets
6736  window->DC.ColumnsOffsetsT.resize((size_t)columns_count + 1);
6737  for (int column_index = 0; column_index < columns_count + 1; column_index++)
6738  {
6739  const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(column_index);
6740  RegisterAliveId(column_id);
6741  const float default_t = column_index / (float)window->DC.ColumnsCount;
6742  const float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store an union into the map?)
6743  window->DC.ColumnsOffsetsT[column_index] = t;
6744  }
6745 
6748  }
6749  else
6750  {
6751  window->DC.ColumnsOffsetsT.resize(2);
6752  window->DC.ColumnsOffsetsT[0] = 0.0f;
6753  window->DC.ColumnsOffsetsT[1] = 1.0f;
6754  }
6755 }
6756 
6757 void ImGui::TreePush(const char* str_id)
6758 {
6759  ImGuiState& g = *GImGui;
6760  ImGuiWindow* window = GetCurrentWindow();
6761  window->DC.ColumnsStartX += g.Style.TreeNodeSpacing;
6762  window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX;
6763  window->DC.TreeDepth++;
6764  PushID(str_id ? str_id : "#TreePush");
6765 }
6766 
6767 void ImGui::TreePush(const void* ptr_id)
6768 {
6769  ImGuiState& g = *GImGui;
6770  ImGuiWindow* window = GetCurrentWindow();
6771  window->DC.ColumnsStartX += g.Style.TreeNodeSpacing;
6772  window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX;
6773  window->DC.TreeDepth++;
6774  PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
6775 }
6776 
6778 {
6779  ImGuiState& g = *GImGui;
6780  ImGuiWindow* window = GetCurrentWindow();
6781  window->DC.ColumnsStartX -= g.Style.TreeNodeSpacing;
6782  window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX;
6783  window->DC.TreeDepth--;
6784  PopID();
6785 }
6786 
6787 void ImGui::Value(const char* prefix, bool b)
6788 {
6789  ImGui::Text("%s: %s", prefix, (b ? "true" : "false"));
6790 }
6791 
6792 void ImGui::Value(const char* prefix, int v)
6793 {
6794  ImGui::Text("%s: %d", prefix, v);
6795 }
6796 
6797 void ImGui::Value(const char* prefix, unsigned int v)
6798 {
6799  ImGui::Text("%s: %d", prefix, v);
6800 }
6801 
6802 void ImGui::Value(const char* prefix, float v, const char* float_format)
6803 {
6804  if (float_format)
6805  {
6806  char fmt[64];
6807  sprintf(fmt, "%%s: %s", float_format);
6808  ImGui::Text(fmt, prefix, v);
6809  }
6810  else
6811  {
6812  ImGui::Text("%s: %.3f", prefix, v);
6813  }
6814 }
6815 
6816 void ImGui::Color(const char* prefix, const ImVec4& v)
6817 {
6818  ImGui::Text("%s: (%.2f,%.2f,%.2f,%.2f)", prefix, v.x, v.y, v.z, v.w);
6819  ImGui::SameLine();
6820  ImGui::ColorButton(v, true);
6821 }
6822 
6823 void ImGui::Color(const char* prefix, unsigned int v)
6824 {
6825  ImGui::Text("%s: %08X", prefix, v);
6826  ImGui::SameLine();
6827 
6828  ImVec4 col;
6829  col.x = (float)((v >> 0) & 0xFF) / 255.0f;
6830  col.y = (float)((v >> 8) & 0xFF) / 255.0f;
6831  col.z = (float)((v >> 16) & 0xFF) / 255.0f;
6832  col.w = (float)((v >> 24) & 0xFF) / 255.0f;
6833  ImGui::ColorButton(col, true);
6834 }
6835 
6836 //-----------------------------------------------------------------------------
6837 // ImDrawList
6838 //-----------------------------------------------------------------------------
6839 
6840 static ImVec4 GNullClipRect(-9999.0f,-9999.0f, +9999.0f, +9999.0f);
6841 
6843 {
6844  commands.resize(0);
6845  vtx_buffer.resize(0);
6846  vtx_write = NULL;
6847  clip_rect_stack.resize(0);
6848  texture_id_stack.resize(0);
6849 }
6850 
6852 {
6853  ImDrawCmd draw_cmd;
6854  draw_cmd.vtx_count = 0;
6855  draw_cmd.clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
6856  draw_cmd.texture_id = texture_id_stack.empty() ? NULL : texture_id_stack.back();
6857  draw_cmd.user_callback = NULL;
6858  draw_cmd.user_callback_data = NULL;
6859  commands.push_back(draw_cmd);
6860 }
6861 
6862 void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
6863 {
6864  ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
6865  if (!current_cmd || current_cmd->vtx_count != 0 || current_cmd->user_callback != NULL)
6866  {
6867  AddDrawCmd();
6868  current_cmd = &commands.back();
6869  }
6870  current_cmd->user_callback = callback;
6871  current_cmd->user_callback_data = callback_data;
6872 
6873  // Force a new command after us
6874  // We function this way so that the most common calls (AddLine, AddRect..) always have a command to add to without doing any check.
6875  AddDrawCmd();
6876 }
6877 
6879 {
6880  ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
6881  if (!current_cmd || (current_cmd->vtx_count != 0) || current_cmd->user_callback != NULL)
6882  {
6883  AddDrawCmd();
6884  }
6885  else
6886  {
6887  current_cmd->clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
6888  }
6889 }
6890 
6891 // Scissoring. The values in clip_rect are x1, y1, x2, y2.
6892 void ImDrawList::PushClipRect(const ImVec4& clip_rect)
6893 {
6894  clip_rect_stack.push_back(clip_rect);
6895  UpdateClipRect();
6896 }
6897 
6899 {
6900  IM_ASSERT(clip_rect_stack.size() > 0);
6901  clip_rect_stack.pop_back();
6902  UpdateClipRect();
6903 }
6904 
6906 {
6907  ImDrawCmd* current_cmd = commands.empty() ? NULL : &commands.back();
6908  const ImTextureID texture_id = texture_id_stack.empty() ? NULL : texture_id_stack.back();
6909  if (!current_cmd || (current_cmd->vtx_count != 0 && current_cmd->texture_id != texture_id) || current_cmd->user_callback != NULL)
6910  {
6911  AddDrawCmd();
6912  }
6913  else
6914  {
6915  current_cmd->texture_id = texture_id;
6916  }
6917 }
6918 
6920 {
6921  texture_id_stack.push_back(texture_id);
6922  UpdateTextureID();
6923 }
6924 
6926 {
6927  IM_ASSERT(texture_id_stack.size() > 0);
6928  texture_id_stack.pop_back();
6929  UpdateTextureID();
6930 }
6931 
6932 void ImDrawList::ReserveVertices(unsigned int vtx_count)
6933 {
6934  if (vtx_count > 0)
6935  {
6936  ImDrawCmd& draw_cmd = commands.back();
6937  draw_cmd.vtx_count += vtx_count;
6938  vtx_buffer.resize(vtx_buffer.size() + vtx_count);
6939  vtx_write = &vtx_buffer[vtx_buffer.size() - vtx_count];
6940  }
6941 }
6942 
6943 void ImDrawList::AddVtx(const ImVec2& pos, ImU32 col)
6944 {
6945  vtx_write->pos = pos;
6946  vtx_write->col = col;
6947  vtx_write->uv = GImGui->FontTexUvWhitePixel;
6948  vtx_write++;
6949 }
6950 
6951 void ImDrawList::AddVtxUV(const ImVec2& pos, ImU32 col, const ImVec2& uv)
6952 {
6953  vtx_write->pos = pos;
6954  vtx_write->col = col;
6955  vtx_write->uv = uv;
6956  vtx_write++;
6957 }
6958 
6959 // NB: memory should be reserved for 6 vertices by the caller.
6960 void ImDrawList::AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col)
6961 {
6962  const float length = sqrtf(ImLengthSqr(b - a));
6963  const ImVec2 hn = (b - a) * (0.50f / length); // half normal
6964  const ImVec2 hp0 = ImVec2(+hn.y, -hn.x); // half perpendiculars + user offset
6965  const ImVec2 hp1 = ImVec2(-hn.y, +hn.x);
6966 
6967  // Two triangles makes up one line. Using triangles allows us to reduce amount of draw calls.
6968  AddVtx(a + hp0, col);
6969  AddVtx(b + hp0, col);
6970  AddVtx(a + hp1, col);
6971  AddVtx(b + hp0, col);
6972  AddVtx(b + hp1, col);
6973  AddVtx(a + hp1, col);
6974 }
6975 
6976 void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col)
6977 {
6978  if ((col >> 24) == 0)
6979  return;
6980 
6981  ReserveVertices(6);
6982  AddVtxLine(a, b, col);
6983 }
6984 
6985 void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, int a_max, bool tris, const ImVec2& third_point_offset)
6986 {
6987  if ((col >> 24) == 0)
6988  return;
6989 
6990  static ImVec2 circle_vtx[12];
6991  static bool circle_vtx_builds = false;
6992  if (!circle_vtx_builds)
6993  {
6994  for (int i = 0; i < IM_ARRAYSIZE(circle_vtx); i++)
6995  {
6996  const float a = ((float)i / (float)IM_ARRAYSIZE(circle_vtx)) * 2*PI;
6997  circle_vtx[i].x = cosf(a + PI);
6998  circle_vtx[i].y = sinf(a + PI);
6999  }
7000  circle_vtx_builds = true;
7001  }
7002 
7003  if (tris)
7004  {
7005  ReserveVertices((unsigned int)(a_max-a_min) * 3);
7006  for (int a = a_min; a < a_max; a++)
7007  {
7008  AddVtx(center + circle_vtx[a % IM_ARRAYSIZE(circle_vtx)] * rad, col);
7009  AddVtx(center + circle_vtx[(a+1) % IM_ARRAYSIZE(circle_vtx)] * rad, col);
7010  AddVtx(center + third_point_offset, col);
7011  }
7012  }
7013  else
7014  {
7015  ReserveVertices((unsigned int)(a_max-a_min) * 6);
7016  for (int a = a_min; a < a_max; a++)
7017  AddVtxLine(center + circle_vtx[a % IM_ARRAYSIZE(circle_vtx)] * rad, center + circle_vtx[(a+1) % IM_ARRAYSIZE(circle_vtx)] * rad, col);
7018  }
7019 }
7020 
7021 void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners)
7022 {
7023  if ((col >> 24) == 0)
7024  return;
7025 
7026  float r = rounding;
7027  r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
7028  r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
7029 
7030  if (r == 0.0f || rounding_corners == 0)
7031  {
7032  ReserveVertices(4*6);
7033  AddVtxLine(ImVec2(a.x,a.y), ImVec2(b.x,a.y), col);
7034  AddVtxLine(ImVec2(b.x,a.y), ImVec2(b.x,b.y), col);
7035  AddVtxLine(ImVec2(b.x,b.y), ImVec2(a.x,b.y), col);
7036  AddVtxLine(ImVec2(a.x,b.y), ImVec2(a.x,a.y), col);
7037  }
7038  else
7039  {
7040  ReserveVertices(4*6);
7041  AddVtxLine(ImVec2(a.x + ((rounding_corners & 1)?r:0), a.y), ImVec2(b.x - ((rounding_corners & 2)?r:0), a.y), col);
7042  AddVtxLine(ImVec2(b.x, a.y + ((rounding_corners & 2)?r:0)), ImVec2(b.x, b.y - ((rounding_corners & 4)?r:0)), col);
7043  AddVtxLine(ImVec2(b.x - ((rounding_corners & 4)?r:0), b.y), ImVec2(a.x + ((rounding_corners & 8)?r:0), b.y), col);
7044  AddVtxLine(ImVec2(a.x, b.y - ((rounding_corners & 8)?r:0)), ImVec2(a.x, a.y + ((rounding_corners & 1)?r:0)), col);
7045 
7046  if (rounding_corners & 1) AddArc(ImVec2(a.x+r,a.y+r), r, col, 0, 3);
7047  if (rounding_corners & 2) AddArc(ImVec2(b.x-r,a.y+r), r, col, 3, 6);
7048  if (rounding_corners & 4) AddArc(ImVec2(b.x-r,b.y-r), r, col, 6, 9);
7049  if (rounding_corners & 8) AddArc(ImVec2(a.x+r,b.y-r), r, col, 9, 12);
7050  }
7051 }
7052 
7053 void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners)
7054 {
7055  if ((col >> 24) == 0)
7056  return;
7057 
7058  float r = rounding;
7059  r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
7060  r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
7061 
7062  if (r == 0.0f || rounding_corners == 0)
7063  {
7064  // Use triangle so we can merge more draw calls together (at the cost of extra vertices)
7065  ReserveVertices(6);
7066  AddVtx(ImVec2(a.x,a.y), col);
7067  AddVtx(ImVec2(b.x,a.y), col);
7068  AddVtx(ImVec2(b.x,b.y), col);
7069  AddVtx(ImVec2(a.x,a.y), col);
7070  AddVtx(ImVec2(b.x,b.y), col);
7071  AddVtx(ImVec2(a.x,b.y), col);
7072  }
7073  else
7074  {
7075  ReserveVertices(6+6*2);
7076  AddVtx(ImVec2(a.x+r,a.y), col);
7077  AddVtx(ImVec2(b.x-r,a.y), col);
7078  AddVtx(ImVec2(b.x-r,b.y), col);
7079  AddVtx(ImVec2(a.x+r,a.y), col);
7080  AddVtx(ImVec2(b.x-r,b.y), col);
7081  AddVtx(ImVec2(a.x+r,b.y), col);
7082 
7083  float top_y = (rounding_corners & 1) ? a.y+r : a.y;
7084  float bot_y = (rounding_corners & 8) ? b.y-r : b.y;
7085  AddVtx(ImVec2(a.x,top_y), col);
7086  AddVtx(ImVec2(a.x+r,top_y), col);
7087  AddVtx(ImVec2(a.x+r,bot_y), col);
7088  AddVtx(ImVec2(a.x,top_y), col);
7089  AddVtx(ImVec2(a.x+r,bot_y), col);
7090  AddVtx(ImVec2(a.x,bot_y), col);
7091 
7092  top_y = (rounding_corners & 2) ? a.y+r : a.y;
7093  bot_y = (rounding_corners & 4) ? b.y-r : b.y;
7094  AddVtx(ImVec2(b.x-r,top_y), col);
7095  AddVtx(ImVec2(b.x,top_y), col);
7096  AddVtx(ImVec2(b.x,bot_y), col);
7097  AddVtx(ImVec2(b.x-r,top_y), col);
7098  AddVtx(ImVec2(b.x,bot_y), col);
7099  AddVtx(ImVec2(b.x-r,bot_y), col);
7100 
7101  if (rounding_corners & 1) AddArc(ImVec2(a.x+r,a.y+r), r, col, 0, 3, true);
7102  if (rounding_corners & 2) AddArc(ImVec2(b.x-r,a.y+r), r, col, 3, 6, true);
7103  if (rounding_corners & 4) AddArc(ImVec2(b.x-r,b.y-r), r, col, 6, 9, true);
7104  if (rounding_corners & 8) AddArc(ImVec2(a.x+r,b.y-r), r, col, 9, 12,true);
7105  }
7106 }
7107 
7108 void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)
7109 {
7110  if ((col >> 24) == 0)
7111  return;
7112 
7113  ReserveVertices(3);
7114  AddVtx(a, col);
7115  AddVtx(b, col);
7116  AddVtx(c, col);
7117 }
7118 
7119 void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments)
7120 {
7121  if ((col >> 24) == 0)
7122  return;
7123 
7124  ReserveVertices((unsigned int)num_segments*6);
7125  const float a_step = 2*PI/(float)num_segments;
7126  float a0 = 0.0f;
7127  for (int i = 0; i < num_segments; i++)
7128  {
7129  const float a1 = (i + 1) == num_segments ? 0.0f : a0 + a_step;
7130  AddVtxLine(centre + ImVec2(cosf(a0), sinf(a0))*radius, centre + ImVec2(cosf(a1), sinf(a1))*radius, col);
7131  a0 = a1;
7132  }
7133 }
7134 
7135 void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
7136 {
7137  if ((col >> 24) == 0)
7138  return;
7139 
7140  ReserveVertices((unsigned int)num_segments*3);
7141  const float a_step = 2*PI/(float)num_segments;
7142  float a0 = 0.0f;
7143  for (int i = 0; i < num_segments; i++)
7144  {
7145  const float a1 = (i + 1) == num_segments ? 0.0f : a0 + a_step;
7146  AddVtx(centre + ImVec2(cosf(a0), sinf(a0))*radius, col);
7147  AddVtx(centre + ImVec2(cosf(a1), sinf(a1))*radius, col);
7148  AddVtx(centre, col);
7149  a0 = a1;
7150  }
7151 }
7152 
7153 void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec2* cpu_clip_max)
7154 {
7155  if ((col >> 24) == 0)
7156  return;
7157 
7158  if (text_end == NULL)
7159  text_end = text_begin + strlen(text_begin);
7160 
7161  IM_ASSERT(font->ContainerAtlas->TexID == texture_id_stack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
7162 
7163  // reserve vertices for worse case
7164  const unsigned int char_count = (unsigned int)(text_end - text_begin);
7165  const unsigned int vtx_count_max = char_count * 6;
7166  const size_t vtx_begin = vtx_buffer.size();
7167  ReserveVertices(vtx_count_max);
7168 
7169  font->RenderText(font_size, pos, col, clip_rect_stack.back(), text_begin, text_end, vtx_write, wrap_width, cpu_clip_max);
7170 
7171  // give back unused vertices
7172  vtx_buffer.resize((size_t)(vtx_write - &vtx_buffer.front()));
7173  const size_t vtx_count = vtx_buffer.size() - vtx_begin;
7174  commands.back().vtx_count -= (unsigned int)(vtx_count_max - vtx_count);
7175  vtx_write -= (vtx_count_max - vtx_count);
7176 }
7177 
7178 void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col)
7179 {
7180  if ((col >> 24) == 0)
7181  return;
7182 
7183  const bool push_texture_id = texture_id_stack.empty() || user_texture_id != texture_id_stack.back();
7184  if (push_texture_id)
7185  PushTextureID(user_texture_id);
7186 
7187  ReserveVertices(6);
7188  AddVtxUV(ImVec2(a.x,a.y), col, uv0);
7189  AddVtxUV(ImVec2(b.x,a.y), col, ImVec2(uv1.x,uv0.y));
7190  AddVtxUV(ImVec2(b.x,b.y), col, uv1);
7191  AddVtxUV(ImVec2(a.x,a.y), col, ImVec2(uv0.x,uv0.y));
7192  AddVtxUV(ImVec2(b.x,b.y), col, uv1);
7193  AddVtxUV(ImVec2(a.x,b.y), col, ImVec2(uv0.x,uv1.y));
7194 
7195  if (push_texture_id)
7196  PopTextureID();
7197 }
7198 
7199 //-----------------------------------------------------------------------------
7200 // ImFontAtlias
7201 //-----------------------------------------------------------------------------
7202 
7203 struct ImFontAtlas::ImFontAtlasData
7204 {
7205  // Input
7206  ImFont* OutFont; // Load into this font
7207  void* TTFData; // TTF data, we own the memory
7208  size_t TTFDataSize; // TTF data size, in bytes
7209  float SizePixels; // Desired output size, in pixels
7210  const ImWchar* GlyphRanges; // List of Unicode range (2 value per range, values are inclusive, zero-terminated list)
7211  int FontNo; // Index of font within .TTF file (0)
7212 
7213  // Temporary Build Data
7214  stbtt_fontinfo FontInfo;
7215  stbrp_rect* Rects;
7216  stbtt_pack_range* Ranges;
7217  int RangesCount;
7218 };
7219 
7221 {
7222  TexID = NULL;
7223  TexPixelsAlpha8 = NULL;
7224  TexPixelsRGBA32 = NULL;
7225  TexWidth = TexHeight = 0;
7226  TexExtraDataPos = TexUvWhitePixel = ImVec2(0, 0);
7227 }
7228 
7230 {
7231  Clear();
7232 }
7233 
7235 {
7236  for (size_t i = 0; i < InputData.size(); i++)
7237  {
7238  if (InputData[i]->TTFData)
7239  ImGui::MemFree(InputData[i]->TTFData);
7240  ImGui::MemFree(InputData[i]);
7241  }
7242  InputData.clear();
7243 }
7244 
7246 {
7247  if (TexPixelsAlpha8)
7248  ImGui::MemFree(TexPixelsAlpha8);
7249  if (TexPixelsRGBA32)
7250  ImGui::MemFree(TexPixelsRGBA32);
7251  TexPixelsAlpha8 = NULL;
7252  TexPixelsRGBA32 = NULL;
7253 }
7254 
7256 {
7257  ClearInputData();
7258  ClearTexData();
7259  for (size_t i = 0; i < Fonts.size(); i++)
7260  {
7261  Fonts[i]->~ImFont();
7262  ImGui::MemFree(Fonts[i]);
7263  }
7264  Fonts.clear();
7265 }
7266 
7267 void ImGui::GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size)
7268 {
7269  printf("GetDefaultFontData() is obsoleted in ImGui 1.30.\n");
7270  printf("Please use ImGui::GetIO().Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() functions to retrieve uncompressed texture data.\n");
7271  if (fnt_data) *fnt_data = NULL;
7272  if (fnt_size) *fnt_size = 0;
7273  if (png_data) *png_data = NULL;
7274  if (png_size) *png_size = 0;
7275  IM_ASSERT(false);
7276 }
7277 
7278 void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
7279 {
7280  // Lazily build
7281  if (TexPixelsAlpha8 == NULL)
7282  {
7283  if (InputData.empty())
7284  AddFontDefault();
7285  Build();
7286  }
7287 
7288  *out_pixels = TexPixelsAlpha8;
7289  if (out_width) *out_width = TexWidth;
7290  if (out_height) *out_height = TexHeight;
7291  if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;
7292 }
7293 
7294 void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
7295 {
7296  // Lazily convert to RGBA32 format
7297  // Although it is likely to be the most commonly used format, our font rendering is 8 bpp
7298  if (!TexPixelsRGBA32)
7299  {
7300  unsigned char* pixels;
7301  GetTexDataAsAlpha8(&pixels, NULL, NULL);
7302  TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4));
7303  const unsigned char* src = pixels;
7304  unsigned int* dst = TexPixelsRGBA32;
7305  for (int n = TexWidth * TexHeight; n > 0; n--)
7306  *dst++ = ((unsigned int)(*src++) << 24) | 0x00FFFFFF;
7307  }
7308 
7309  *out_pixels = (unsigned char*)TexPixelsRGBA32;
7310  if (out_width) *out_width = TexWidth;
7311  if (out_height) *out_height = TexHeight;
7312  if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;
7313 }
7314 
7315 static void GetDefaultCompressedFontDataTTF(const void** ttf_compressed_data, unsigned int* ttf_compressed_size);
7316 static unsigned int stb_decompress_length(unsigned char *input);
7317 static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);
7318 
7319 // Load embedded ProggyClean.ttf at size 13
7321 {
7322  // Get compressed data
7323  unsigned int ttf_compressed_size;
7324  const void* ttf_compressed;
7325  GetDefaultCompressedFontDataTTF(&ttf_compressed, &ttf_compressed_size);
7326 
7327  // Decompress
7328  const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)ttf_compressed);
7329  unsigned char* buf_decompressed = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);
7330  stb_decompress(buf_decompressed, (unsigned char*)ttf_compressed, ttf_compressed_size);
7331 
7332  // Add
7333  ImFont* font = AddFontFromMemoryTTF(buf_decompressed, buf_decompressed_size, 13.0f, GetGlyphRangesDefault(), 0);
7334  font->DisplayOffset.y += 1;
7335  return font;
7336 }
7337 
7338 ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImWchar* glyph_ranges, int font_no)
7339 {
7340  void* data = NULL;
7341  size_t data_size = 0;
7342  if (!ImLoadFileToMemory(filename, "rb", (void**)&data, &data_size))
7343  {
7344  IM_ASSERT(0); // Could not load file.
7345  return NULL;
7346  }
7347 
7348  // Add
7349  ImFont* font = AddFontFromMemoryTTF(data, data_size, size_pixels, glyph_ranges, font_no);
7350  return font;
7351 }
7352 
7353 // NB: ownership of 'data' is given to ImFontAtlas which will clear it.
7354 ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, size_t in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no)
7355 {
7356  // Create new font
7357  ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont));
7358  new (font) ImFont();
7359  Fonts.push_back(font);
7360 
7361  // Add to build list
7362  ImFontAtlasData* data = (ImFontAtlasData*)ImGui::MemAlloc(sizeof(ImFontAtlasData));
7363  memset(data, 0, sizeof(ImFontAtlasData));
7364  data->OutFont = font;
7365  data->TTFData = in_ttf_data;
7366  data->TTFDataSize = in_ttf_data_size;
7367  data->SizePixels = size_pixels;
7368  data->GlyphRanges = glyph_ranges;
7369  data->FontNo = font_no;
7370  InputData.push_back(data);
7371 
7372  // Invalidate texture
7373  ClearTexData();
7374 
7375  return font;
7376 }
7377 
7379 {
7380  IM_ASSERT(InputData.size() > 0);
7381 
7382  TexID = NULL;
7383  TexWidth = TexHeight = 0;
7384  TexExtraDataPos = TexUvWhitePixel = ImVec2(0, 0);
7385  ClearTexData();
7386 
7387  // Initialize font information early (so we can error without any cleanup) + count glyphs
7388  int total_glyph_count = 0;
7389  int total_glyph_range_count = 0;
7390  for (size_t input_i = 0; input_i < InputData.size(); input_i++)
7391  {
7392  ImFontAtlasData& data = *InputData[input_i];
7393  IM_ASSERT(data.OutFont && !data.OutFont->IsLoaded());
7394  const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)data.TTFData, data.FontNo);
7395  IM_ASSERT(font_offset >= 0);
7396  if (!stbtt_InitFont(&data.FontInfo, (unsigned char*)data.TTFData, font_offset))
7397  return false;
7398 
7399  if (!data.GlyphRanges)
7400  data.GlyphRanges = GetGlyphRangesDefault();
7401  for (const ImWchar* in_range = data.GlyphRanges; in_range[0] && in_range[1]; in_range += 2)
7402  {
7403  total_glyph_count += (in_range[1] - in_range[0]) + 1;
7404  total_glyph_range_count++;
7405  }
7406  }
7407 
7408  // Start packing
7409  TexWidth = (total_glyph_count > 1000) ? 1024 : 512; // Width doesn't actually matters.
7410  TexHeight = 0;
7411  const int max_tex_height = 1024*32;
7412  stbtt_pack_context spc;
7413  int ret = stbtt_PackBegin(&spc, NULL, TexWidth, max_tex_height, 0, 1, NULL);
7414  IM_ASSERT(ret);
7415  stbtt_PackSetOversampling(&spc, 1, 1);
7416 
7417  // Pack our extra data rectangle first, so it will be on the upper-left corner of our texture (UV will have small values).
7418  stbrp_rect extra_rect;
7419  extra_rect.w = (stbrp_coord)TEX_ATLAS_SIZE.x;
7420  extra_rect.h = (stbrp_coord)TEX_ATLAS_SIZE.y;
7421  stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
7422  TexExtraDataPos = ImVec2(extra_rect.x, extra_rect.y);
7423 
7424  // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
7425  int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;
7426  stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar));
7427  stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect));
7428  stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range));
7429  memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar));
7430  memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect)); // Unnessary but let's clear this for the sake of sanity.
7431  memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range));
7432 
7433  // First pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
7434  int tex_height = extra_rect.y + extra_rect.h;
7435  for (size_t input_i = 0; input_i < InputData.size(); input_i++)
7436  {
7437  ImFontAtlasData& data = *InputData[input_i];
7438 
7439  // Setup ranges
7440  int glyph_count = 0;
7441  int glyph_ranges_count = 0;
7442  for (const ImWchar* in_range = data.GlyphRanges; in_range[0] && in_range[1]; in_range += 2)
7443  {
7444  glyph_count += (in_range[1] - in_range[0]) + 1;
7445  glyph_ranges_count++;
7446  }
7447  data.Ranges = buf_ranges + buf_ranges_n;
7448  data.RangesCount = glyph_ranges_count;
7449  buf_ranges_n += glyph_ranges_count;
7450  for (int i = 0; i < glyph_ranges_count; i++)
7451  {
7452  const ImWchar* in_range = &data.GlyphRanges[i * 2];
7453  stbtt_pack_range& range = data.Ranges[i];
7454  range.font_size = data.SizePixels;
7455  range.first_unicode_char_in_range = in_range[0];
7456  range.num_chars_in_range = (in_range[1] - in_range[0]) + 1;
7457  range.chardata_for_range = buf_packedchars + buf_packedchars_n;
7458  buf_packedchars_n += range.num_chars_in_range;
7459  }
7460 
7461  // Pack
7462  data.Rects = buf_rects + buf_rects_n;
7463  buf_rects_n += glyph_count;
7464  const int n = stbtt_PackFontRangesGatherRects(&spc, &data.FontInfo, data.Ranges, data.RangesCount, data.Rects);
7465  stbrp_pack_rects((stbrp_context*)spc.pack_info, data.Rects, n);
7466 
7467  // Extend texture height
7468  for (int i = 0; i < n; i++)
7469  if (data.Rects[i].was_packed)
7470  tex_height = ImMax(tex_height, data.Rects[i].y + data.Rects[i].h);
7471  }
7472  IM_ASSERT(buf_rects_n == total_glyph_count);
7473  IM_ASSERT(buf_packedchars_n == total_glyph_count);
7474  IM_ASSERT(buf_ranges_n == total_glyph_range_count);
7475 
7476  // Create texture
7477  TexHeight = ImUpperPowerOfTwo(tex_height);
7478  TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(TexWidth * TexHeight);
7479  memset(TexPixelsAlpha8, 0, TexWidth * TexHeight);
7480  spc.pixels = TexPixelsAlpha8;
7481  spc.height = TexHeight;
7482 
7483  // Second pass: render characters
7484  for (size_t input_i = 0; input_i < InputData.size(); input_i++)
7485  {
7486  ImFontAtlasData& data = *InputData[input_i];
7487  ret = stbtt_PackFontRangesRenderIntoRects(&spc, &data.FontInfo, data.Ranges, data.RangesCount, data.Rects);
7488  data.Rects = NULL;
7489  }
7490 
7491  // End packing
7492  stbtt_PackEnd(&spc);
7493  ImGui::MemFree(buf_rects);
7494  buf_rects = NULL;
7495 
7496  // Third pass: setup ImFont and glyphs for runtime
7497  for (size_t input_i = 0; input_i < InputData.size(); input_i++)
7498  {
7499  ImFontAtlasData& data = *InputData[input_i];
7500  data.OutFont->ContainerAtlas = this;
7501  data.OutFont->FontSize = data.SizePixels;
7502 
7503  const float font_scale = stbtt_ScaleForPixelHeight(&data.FontInfo, data.SizePixels);
7504  int font_ascent, font_descent, font_line_gap;
7505  stbtt_GetFontVMetrics(&data.FontInfo, &font_ascent, &font_descent, &font_line_gap);
7506 
7507  const float uv_scale_x = 1.0f / TexWidth;
7508  const float uv_scale_y = 1.0f / TexHeight;
7509  const int character_spacing_x = 1;
7510  for (int i = 0; i < data.RangesCount; i++)
7511  {
7512  stbtt_pack_range& range = data.Ranges[i];
7513  for (int char_idx = 0; char_idx < range.num_chars_in_range; char_idx += 1)
7514  {
7515  const int codepoint = range.first_unicode_char_in_range + char_idx;
7516  const stbtt_packedchar& pc = range.chardata_for_range[char_idx];
7517  if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1)
7518  continue;
7519 
7520  data.OutFont->Glyphs.resize(data.OutFont->Glyphs.size() + 1);
7521  ImFont::Glyph& glyph = data.OutFont->Glyphs.back();
7522  glyph.Codepoint = (ImWchar)codepoint;
7523  glyph.Width = (signed short)pc.x1 - pc.x0 + 1;
7524  glyph.Height = (signed short)pc.y1 - pc.y0 + 1;
7525  glyph.XOffset = (signed short)(pc.xoff);
7526  glyph.YOffset = (signed short)(pc.yoff + (int)(font_ascent * font_scale));
7527  glyph.XAdvance = (signed short)(pc.xadvance + character_spacing_x); // Bake spacing into XAdvance
7528  glyph.U0 = ((float)pc.x0 - 0.5f) * uv_scale_x;
7529  glyph.V0 = ((float)pc.y0 - 0.5f) * uv_scale_y;
7530  glyph.U1 = ((float)pc.x0 - 0.5f + glyph.Width) * uv_scale_x;
7531  glyph.V1 = ((float)pc.y0 - 0.5f + glyph.Height) * uv_scale_y;
7532  }
7533  }
7534 
7535  data.OutFont->BuildLookupTable();
7536  }
7537 
7538  // Cleanup temporaries
7539  ImGui::MemFree(buf_packedchars);
7540  ImGui::MemFree(buf_ranges);
7541  buf_packedchars = NULL;
7542  buf_ranges = NULL;
7543  ClearInputData();
7544 
7545  // Render into our custom data block
7546  RenderCustomTexData();
7547 
7548  return true;
7549 }
7550 
7552 {
7553  IM_ASSERT(TexExtraDataPos.x == 0.0f && TexExtraDataPos.y == 0.0f);
7554 
7555  // Draw white pixel into texture and make UV points to it
7556  TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
7557  TexUvWhitePixel = ImVec2((TexExtraDataPos.x + 0.5f) / TexWidth, (TexExtraDataPos.y + 0.5f) / TexHeight);
7558 
7559  // Draw a mouse cursor into texture
7560  // Because our font uses a single color channel, we have to spread the cursor in 2 layers (black/white) which will be rendered separately.
7561  const char cursor_pixels[] =
7562  {
7563  "X "
7564  "XX "
7565  "X.X "
7566  "X..X "
7567  "X...X "
7568  "X....X "
7569  "X.....X "
7570  "X......X "
7571  "X.......X "
7572  "X........X "
7573  "X.........X "
7574  "X..........X"
7575  "X......XXXXX"
7576  "X...X..X "
7577  "X..X X..X "
7578  "X.X X..X "
7579  "XX X..X "
7580  " X..X "
7581  " XX "
7582  };
7583  IM_ASSERT(sizeof(cursor_pixels)-1 == (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.x * (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.y);
7584  for (int y = 0, n = 0; y < 19; y++)
7585  for (int x = 0; x < 12; x++, n++)
7586  {
7587  TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.y + y) * TexWidth] = (cursor_pixels[n] == 'X') ? 0xFF : 0x00;
7588  TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.y + y) * TexWidth] = (cursor_pixels[n] == '.') ? 0xFF : 0x00;
7589  }
7590 }
7591 
7592 //-----------------------------------------------------------------------------
7593 // ImFont
7594 //-----------------------------------------------------------------------------
7595 
7597 {
7598  Scale = 1.0f;
7599  FallbackChar = (ImWchar)'?';
7600  Clear();
7601 }
7602 
7604 {
7605  FontSize = 0.0f;
7606  DisplayOffset = ImVec2(-0.5f, 0.5f);
7607  ContainerAtlas = NULL;
7608  Glyphs.clear();
7609  FallbackGlyph = NULL;
7610  FallbackXAdvance = 0.0f;
7611  IndexXAdvance.clear();
7612  IndexLookup.clear();
7613 }
7614 
7615 // Retrieve list of range (2 int per range, values are inclusive)
7617 {
7618  static const ImWchar ranges[] =
7619  {
7620  0x0020, 0x00FF, // Basic Latin + Latin Supplement
7621  0,
7622  };
7623  return &ranges[0];
7624 }
7625 
7627 {
7628  static const ImWchar ranges[] =
7629  {
7630  0x0020, 0x00FF, // Basic Latin + Latin Supplement
7631  0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
7632  0x31F0, 0x31FF, // Katakana Phonetic Extensions
7633  0xFF00, 0xFFEF, // Half-width characters
7634  0x4e00, 0x9FAF, // CJK Ideograms
7635  0,
7636  };
7637  return &ranges[0];
7638 }
7639 
7641 {
7642  // Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1.
7643  // This encoding helps us reduce the source code size.
7644  static const short offsets_from_0x4E00[] =
7645  {
7646  -1,0,1,3,0,0,0,0,1,0,5,1,1,0,7,4,6,10,0,1,9,9,7,1,3,19,1,10,7,1,0,1,0,5,1,0,6,4,2,6,0,0,12,6,8,0,3,5,0,1,0,9,0,0,8,1,1,3,4,5,13,0,0,8,2,17,
7647  4,3,1,1,9,6,0,0,0,2,1,3,2,22,1,9,11,1,13,1,3,12,0,5,9,2,0,6,12,5,3,12,4,1,2,16,1,1,4,6,5,3,0,6,13,15,5,12,8,14,0,0,6,15,3,6,0,18,8,1,6,14,1,
7648  5,4,12,24,3,13,12,10,24,0,0,0,1,0,1,1,2,9,10,2,2,0,0,3,3,1,0,3,8,0,3,2,4,4,1,6,11,10,14,6,15,3,4,15,1,0,0,5,2,2,0,0,1,6,5,5,6,0,3,6,5,0,0,1,0,
7649  11,2,2,8,4,7,0,10,0,1,2,17,19,3,0,2,5,0,6,2,4,4,6,1,1,11,2,0,3,1,2,1,2,10,7,6,3,16,0,8,24,0,0,3,1,1,3,0,1,6,0,0,0,2,0,1,5,15,0,1,0,0,2,11,19,
7650  1,4,19,7,6,5,1,0,0,0,0,5,1,0,1,9,0,0,5,0,2,0,1,0,3,0,11,3,0,2,0,0,0,0,0,9,3,6,4,12,0,14,0,0,29,10,8,0,14,37,13,0,31,16,19,0,8,30,1,20,8,3,48,
7651  21,1,0,12,0,10,44,34,42,54,11,18,82,0,2,1,2,12,1,0,6,2,17,2,12,7,0,7,17,4,2,6,24,23,8,23,39,2,16,23,1,0,5,1,2,15,14,5,6,2,11,0,8,6,2,2,2,14,
7652  20,4,15,3,4,11,10,10,2,5,2,1,30,2,1,0,0,22,5,5,0,3,1,5,4,1,0,0,2,2,21,1,5,1,2,16,2,1,3,4,0,8,4,0,0,5,14,11,2,16,1,13,1,7,0,22,15,3,1,22,7,14,
7653  22,19,11,24,18,46,10,20,64,45,3,2,0,4,5,0,1,4,25,1,0,0,2,10,0,0,0,1,0,1,2,0,0,9,1,2,0,0,0,2,5,2,1,1,5,5,8,1,1,1,5,1,4,9,1,3,0,1,0,1,1,2,0,0,
7654  2,0,1,8,22,8,1,0,0,0,0,4,2,1,0,9,8,5,0,9,1,30,24,2,6,4,39,0,14,5,16,6,26,179,0,2,1,1,0,0,0,5,2,9,6,0,2,5,16,7,5,1,1,0,2,4,4,7,15,13,14,0,0,
7655  3,0,1,0,0,0,2,1,6,4,5,1,4,9,0,3,1,8,0,0,10,5,0,43,0,2,6,8,4,0,2,0,0,9,6,0,9,3,1,6,20,14,6,1,4,0,7,2,3,0,2,0,5,0,3,1,0,3,9,7,0,3,4,0,4,9,1,6,0,
7656  9,0,0,2,3,10,9,28,3,6,2,4,1,2,32,4,1,18,2,0,3,1,5,30,10,0,2,2,2,0,7,9,8,11,10,11,7,2,13,7,5,10,0,3,40,2,0,1,6,12,0,4,5,1,5,11,11,21,4,8,3,7,
7657  8,8,33,5,23,0,0,19,8,8,2,3,0,6,1,1,1,5,1,27,4,2,5,0,3,5,6,3,1,0,3,1,12,5,3,3,2,0,7,7,2,1,0,4,0,1,1,2,0,10,10,6,2,5,9,7,5,15,15,21,6,11,5,20,
7658  4,3,5,5,2,5,0,2,1,0,1,7,28,0,9,0,5,12,5,5,18,30,0,12,3,3,21,16,25,32,9,3,14,11,24,5,66,9,1,2,0,5,9,1,5,1,8,0,8,3,3,0,1,15,1,4,8,1,2,7,0,7,2,
7659  8,3,7,5,3,7,10,2,1,0,0,2,25,0,6,4,0,10,0,4,2,4,1,12,5,38,4,0,4,1,10,5,9,4,0,14,4,2,5,18,20,21,1,3,0,5,0,7,0,3,7,1,3,1,1,8,1,0,0,0,3,2,5,2,11,
7660  6,0,13,1,3,9,1,12,0,16,6,2,1,0,2,1,12,6,13,11,2,0,28,1,7,8,14,13,8,13,0,2,0,5,4,8,10,2,37,42,19,6,6,7,4,14,11,18,14,80,7,6,0,4,72,12,36,27,
7661  7,7,0,14,17,19,164,27,0,5,10,7,3,13,6,14,0,2,2,5,3,0,6,13,0,0,10,29,0,4,0,3,13,0,3,1,6,51,1,5,28,2,0,8,0,20,2,4,0,25,2,10,13,10,0,16,4,0,1,0,
7662  2,1,7,0,1,8,11,0,0,1,2,7,2,23,11,6,6,4,16,2,2,2,0,22,9,3,3,5,2,0,15,16,21,2,9,20,15,15,5,3,9,1,0,0,1,7,7,5,4,2,2,2,38,24,14,0,0,15,5,6,24,14,
7663  5,5,11,0,21,12,0,3,8,4,11,1,8,0,11,27,7,2,4,9,21,59,0,1,39,3,60,62,3,0,12,11,0,3,30,11,0,13,88,4,15,5,28,13,1,4,48,17,17,4,28,32,46,0,16,0,
7664  18,11,1,8,6,38,11,2,6,11,38,2,0,45,3,11,2,7,8,4,30,14,17,2,1,1,65,18,12,16,4,2,45,123,12,56,33,1,4,3,4,7,0,0,0,3,2,0,16,4,2,4,2,0,7,4,5,2,26,
7665  2,25,6,11,6,1,16,2,6,17,77,15,3,35,0,1,0,5,1,0,38,16,6,3,12,3,3,3,0,9,3,1,3,5,2,9,0,18,0,25,1,3,32,1,72,46,6,2,7,1,3,14,17,0,28,1,40,13,0,20,
7666  15,40,6,38,24,12,43,1,1,9,0,12,6,0,6,2,4,19,3,7,1,48,0,9,5,0,5,6,9,6,10,15,2,11,19,3,9,2,0,1,10,1,27,8,1,3,6,1,14,0,26,0,27,16,3,4,9,6,2,23,
7667  9,10,5,25,2,1,6,1,1,48,15,9,15,14,3,4,26,60,29,13,37,21,1,6,4,0,2,11,22,23,16,16,2,2,1,3,0,5,1,6,4,0,0,4,0,0,8,3,0,2,5,0,7,1,7,3,13,2,4,10,
7668  3,0,2,31,0,18,3,0,12,10,4,1,0,7,5,7,0,5,4,12,2,22,10,4,2,15,2,8,9,0,23,2,197,51,3,1,1,4,13,4,3,21,4,19,3,10,5,40,0,4,1,1,10,4,1,27,34,7,21,
7669  2,17,2,9,6,4,2,3,0,4,2,7,8,2,5,1,15,21,3,4,4,2,2,17,22,1,5,22,4,26,7,0,32,1,11,42,15,4,1,2,5,0,19,3,1,8,6,0,10,1,9,2,13,30,8,2,24,17,19,1,4,
7670  4,25,13,0,10,16,11,39,18,8,5,30,82,1,6,8,18,77,11,13,20,75,11,112,78,33,3,0,0,60,17,84,9,1,1,12,30,10,49,5,32,158,178,5,5,6,3,3,1,3,1,4,7,6,
7671  19,31,21,0,2,9,5,6,27,4,9,8,1,76,18,12,1,4,0,3,3,6,3,12,2,8,30,16,2,25,1,5,5,4,3,0,6,10,2,3,1,0,5,1,19,3,0,8,1,5,2,6,0,0,0,19,1,2,0,5,1,2,5,
7672  1,3,7,0,4,12,7,3,10,22,0,9,5,1,0,2,20,1,1,3,23,30,3,9,9,1,4,191,14,3,15,6,8,50,0,1,0,0,4,0,0,1,0,2,4,2,0,2,3,0,2,0,2,2,8,7,0,1,1,1,3,3,17,11,
7673  91,1,9,3,2,13,4,24,15,41,3,13,3,1,20,4,125,29,30,1,0,4,12,2,21,4,5,5,19,11,0,13,11,86,2,18,0,7,1,8,8,2,2,22,1,2,6,5,2,0,1,2,8,0,2,0,5,2,1,0,
7674  2,10,2,0,5,9,2,1,2,0,1,0,4,0,0,10,2,5,3,0,6,1,0,1,4,4,33,3,13,17,3,18,6,4,7,1,5,78,0,4,1,13,7,1,8,1,0,35,27,15,3,0,0,0,1,11,5,41,38,15,22,6,
7675  14,14,2,1,11,6,20,63,5,8,27,7,11,2,2,40,58,23,50,54,56,293,8,8,1,5,1,14,0,1,12,37,89,8,8,8,2,10,6,0,0,0,4,5,2,1,0,1,1,2,7,0,3,3,0,4,6,0,3,2,
7676  19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20,
7677  109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
7678  };
7679  static int ranges_unpacked = false;
7680  static ImWchar ranges[8 + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1] =
7681  {
7682  0x0020, 0x00FF, // Basic Latin + Latin Supplement
7683  0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
7684  0x31F0, 0x31FF, // Katakana Phonetic Extensions
7685  0xFF00, 0xFFEF, // Half-width characters
7686  };
7687  if (!ranges_unpacked)
7688  {
7689  // Unpack
7690  int codepoint = 0x4e00;
7691  ImWchar* dst = &ranges[8];
7692  for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
7693  dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
7694  dst[0] = 0;
7695  ranges_unpacked = true;
7696  }
7697  return &ranges[0];
7698 }
7699 
7701 {
7702  int max_codepoint = 0;
7703  for (size_t i = 0; i != Glyphs.size(); i++)
7704  max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);
7705 
7706  IndexXAdvance.clear();
7707  IndexXAdvance.resize((size_t)max_codepoint + 1);
7708  IndexLookup.clear();
7709  IndexLookup.resize((size_t)max_codepoint + 1);
7710  for (size_t i = 0; i < (size_t)max_codepoint + 1; i++)
7711  {
7712  IndexXAdvance[i] = -1.0f;
7713  IndexLookup[i] = -1;
7714  }
7715  for (size_t i = 0; i < Glyphs.size(); i++)
7716  {
7717  const size_t codepoint = (int)Glyphs[i].Codepoint;
7718  IndexXAdvance[codepoint] = Glyphs[i].XAdvance;
7719  IndexLookup[codepoint] = (int)i;
7720  }
7721 
7722  // Create a glyph to handle TAB
7723  // FIXME: Needs proper TAB handling but it needs to be contextualized (can arbitrary say that each string starts at "column 0"
7724  if (FindGlyph((unsigned short)' '))
7725  {
7726  if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times
7727  Glyphs.resize(Glyphs.size() + 1);
7728  ImFont::Glyph& tab_glyph = Glyphs.back();
7729  tab_glyph = *FindGlyph((unsigned short)' ');
7730  tab_glyph.Codepoint = '\t';
7731  tab_glyph.XAdvance *= 4;
7732  IndexXAdvance[(size_t)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance;
7733  IndexLookup[(size_t)tab_glyph.Codepoint] = (int)(Glyphs.size()-1);
7734  }
7735 
7736  FallbackGlyph = NULL;
7737  FallbackGlyph = FindGlyph(FallbackChar);
7738  FallbackXAdvance = FallbackGlyph ? FallbackGlyph->XAdvance : 0.0f;
7739  for (size_t i = 0; i < (size_t)max_codepoint + 1; i++)
7740  if (IndexXAdvance[i] < 0.0f)
7741  IndexXAdvance[i] = FallbackXAdvance;
7742 }
7743 
7745 {
7746  FallbackChar = c;
7747  BuildLookupTable();
7748 }
7749 
7750 const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const
7751 {
7752  if (c < (int)IndexLookup.size())
7753  {
7754  const int i = IndexLookup[c];
7755  if (i != -1)
7756  return &Glyphs[i];
7757  }
7758  return FallbackGlyph;
7759 }
7760 
7761 // Convert UTF-8 to 32-bits character, process single character input.
7762 // Based on stb_from_utf8() from github.com/nothings/stb/
7763 // We handle UTF-8 decoding error by skipping forward.
7764 static int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
7765 {
7766  unsigned int c = (unsigned int)-1;
7767  const unsigned char* str = (const unsigned char*)in_text;
7768  if (!(*str & 0x80))
7769  {
7770  c = (unsigned int)(*str++);
7771  *out_char = c;
7772  return 1;
7773  }
7774  if ((*str & 0xe0) == 0xc0)
7775  {
7776  *out_char = 0;
7777  if (in_text_end && in_text_end - (const char*)str < 2) return 0;
7778  if (*str < 0xc2) return 0;
7779  c = (unsigned int)((*str++ & 0x1f) << 6);
7780  if ((*str & 0xc0) != 0x80) return 0;
7781  c += (*str++ & 0x3f);
7782  *out_char = c;
7783  return 2;
7784  }
7785  if ((*str & 0xf0) == 0xe0)
7786  {
7787  *out_char = 0;
7788  if (in_text_end && in_text_end - (const char*)str < 3) return 0;
7789  if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 0;
7790  if (*str == 0xed && str[1] > 0x9f) return 0; // str[1] < 0x80 is checked below
7791  c = (unsigned int)((*str++ & 0x0f) << 12);
7792  if ((*str & 0xc0) != 0x80) return 0;
7793  c += (unsigned int)((*str++ & 0x3f) << 6);
7794  if ((*str & 0xc0) != 0x80) return 0;
7795  c += (*str++ & 0x3f);
7796  *out_char = c;
7797  return 3;
7798  }
7799  if ((*str & 0xf8) == 0xf0)
7800  {
7801  *out_char = 0;
7802  if (in_text_end && in_text_end - (const char*)str < 4) return 0;
7803  if (*str > 0xf4) return 0;
7804  if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 0;
7805  if (*str == 0xf4 && str[1] > 0x8f) return 0; // str[1] < 0x80 is checked below
7806  c = (unsigned int)((*str++ & 0x07) << 18);
7807  if ((*str & 0xc0) != 0x80) return 0;
7808  c += (unsigned int)((*str++ & 0x3f) << 12);
7809  if ((*str & 0xc0) != 0x80) return 0;
7810  c += (unsigned int)((*str++ & 0x3f) << 6);
7811  if ((*str & 0xc0) != 0x80) return 0;
7812  c += (*str++ & 0x3f);
7813  // utf-8 encodings of values used in surrogate pairs are invalid
7814  if ((c & 0xFFFFF800) == 0xD800) return 0;
7815  *out_char = c;
7816  return 4;
7817  }
7818  *out_char = 0;
7819  return 0;
7820 }
7821 
7822 static ptrdiff_t ImTextStrFromUtf8(ImWchar* buf, size_t buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
7823 {
7824  ImWchar* buf_out = buf;
7825  ImWchar* buf_end = buf + buf_size;
7826  while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
7827  {
7828  unsigned int c;
7829  in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7830  if (c == 0)
7831  break;
7832  if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes
7833  *buf_out++ = (ImWchar)c;
7834  }
7835  *buf_out = 0;
7836  if (in_text_remaining)
7837  *in_text_remaining = in_text;
7838  return buf_out - buf;
7839 }
7840 
7841 static int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
7842 {
7843  int char_count = 0;
7844  while ((!in_text_end || in_text < in_text_end) && *in_text)
7845  {
7846  unsigned int c;
7847  in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
7848  if (c == 0)
7849  break;
7850  if (c < 0x10000)
7851  char_count++;
7852  }
7853  return char_count;
7854 }
7855 
7856 // Based on stb_to_utf8() from github.com/nothings/stb/
7857 static int ImTextCharToUtf8(char* buf, size_t buf_size, unsigned int c)
7858 {
7859  if (c)
7860  {
7861  size_t i = 0;
7862  size_t n = buf_size;
7863  if (c < 0x80)
7864  {
7865  if (i+1 > n) return 0;
7866  buf[i++] = (char)c;
7867  return 1;
7868  }
7869  else if (c < 0x800)
7870  {
7871  if (i+2 > n) return 0;
7872  buf[i++] = (char)(0xc0 + (c >> 6));
7873  buf[i++] = (char)(0x80 + (c & 0x3f));
7874  return 2;
7875  }
7876  else if (c >= 0xdc00 && c < 0xe000)
7877  {
7878  return 0;
7879  }
7880  else if (c >= 0xd800 && c < 0xdc00)
7881  {
7882  if (i+4 > n) return 0;
7883  buf[i++] = (char)(0xf0 + (c >> 18));
7884  buf[i++] = (char)(0x80 + ((c >> 12) & 0x3f));
7885  buf[i++] = (char)(0x80 + ((c >> 6) & 0x3f));
7886  buf[i++] = (char)(0x80 + ((c ) & 0x3f));
7887  return 4;
7888  }
7889  //else if (c < 0x10000)
7890  {
7891  if (i+3 > n) return 0;
7892  buf[i++] = (char)(0xe0 + (c >> 12));
7893  buf[i++] = (char)(0x80 + ((c>> 6) & 0x3f));
7894  buf[i++] = (char)(0x80 + ((c ) & 0x3f));
7895  return 3;
7896  }
7897  }
7898  return 0;
7899 }
7900 
7901 static ptrdiff_t ImTextStrToUtf8(char* buf, size_t buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
7902 {
7903  char* buf_out = buf;
7904  const char* buf_end = buf + buf_size;
7905  while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
7906  {
7907  buf_out += ImTextCharToUtf8(buf_out, (uintptr_t)(buf_end-buf_out-1), (unsigned int)*in_text);
7908  in_text++;
7909  }
7910  *buf_out = 0;
7911  return buf_out - buf;
7912 }
7913 
7914 static int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
7915 {
7916  int bytes_count = 0;
7917  while ((!in_text_end || in_text < in_text_end) && *in_text)
7918  {
7919  char dummy[5]; // FIXME-OPT
7920  bytes_count += ImTextCharToUtf8(dummy, 5, (unsigned int)*in_text);
7921  in_text++;
7922  }
7923  return bytes_count;
7924 }
7925 
7926 const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
7927 {
7928  // Simple word-wrapping for English, not full-featured. Please submit failing cases!
7929  // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
7930 
7931  // For references, possible wrap point marked with ^
7932  // "aaa bbb, ccc,ddd. eee fff. ggg!"
7933  // ^ ^ ^ ^ ^__ ^ ^
7934 
7935  // List of hardcoded separators: .,;!?'"
7936 
7937  // Skip extra blanks after a line returns (that includes not counting them in width computation)
7938  // e.g. "Hello world" --> "Hello" "World"
7939 
7940  // Cut words that cannot possibly fit within one line.
7941  // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish"
7942 
7943  float line_width = 0.0f;
7944  float word_width = 0.0f;
7945  float blank_width = 0.0f;
7946 
7947  const char* word_end = text;
7948  const char* prev_word_end = NULL;
7949  bool inside_word = true;
7950 
7951  const char* s = text;
7952  while (s < text_end)
7953  {
7954  unsigned int c = (unsigned int)*s;
7955  const char* next_s;
7956  if (c < 0x80)
7957  next_s = s + 1;
7958  else
7959  next_s = s + ImTextCharFromUtf8(&c, s, text_end);
7960  if (c == 0)
7961  break;
7962 
7963  if (c == '\n')
7964  {
7965  line_width = word_width = blank_width = 0.0f;
7966  inside_word = true;
7967  s = next_s;
7968  continue;
7969  }
7970 
7971  const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
7972  if (ImCharIsSpace(c))
7973  {
7974  if (inside_word)
7975  {
7976  line_width += blank_width;
7977  blank_width = 0.0f;
7978  }
7979  blank_width += char_width;
7980  inside_word = false;
7981  }
7982  else
7983  {
7984  word_width += char_width;
7985  if (inside_word)
7986  {
7987  word_end = next_s;
7988  }
7989  else
7990  {
7991  prev_word_end = word_end;
7992  line_width += word_width + blank_width;
7993  word_width = blank_width = 0.0f;
7994  }
7995 
7996  // Allow wrapping after punctuation.
7997  inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\"');
7998  }
7999 
8000  // We ignore blank width at the end of the line (they can be skipped)
8001  if (line_width + word_width >= wrap_width)
8002  {
8003  // Words that cannot possibly fit within an entire line will be cut anywhere.
8004  if (word_width < wrap_width)
8005  s = prev_word_end ? prev_word_end : word_end;
8006  break;
8007  }
8008 
8009  s = next_s;
8010  }
8011 
8012  return s;
8013 }
8014 
8015 ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
8016 {
8017  if (!text_end)
8018  text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.
8019 
8020  const float scale = size / FontSize;
8021  const float line_height = FontSize * scale;
8022 
8023  ImVec2 text_size = ImVec2(0,0);
8024  float line_width = 0.0f;
8025 
8026  const bool word_wrap_enabled = (wrap_width > 0.0f);
8027  const char* word_wrap_eol = NULL;
8028 
8029  const char* s = text_begin;
8030  while (s < text_end)
8031  {
8032  if (word_wrap_enabled)
8033  {
8034  // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
8035  if (!word_wrap_eol)
8036  {
8037  word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);
8038  if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
8039  word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
8040  }
8041 
8042  if (s >= word_wrap_eol)
8043  {
8044  if (text_size.x < line_width)
8045  text_size.x = line_width;
8046  text_size.y += line_height;
8047  line_width = 0.0f;
8048  word_wrap_eol = NULL;
8049 
8050  // Wrapping skips upcoming blanks
8051  while (s < text_end)
8052  {
8053  const char c = *s;
8054  if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
8055  }
8056  continue;
8057  }
8058  }
8059 
8060  // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
8061  unsigned int c = (unsigned int)*s;
8062  if (c < 0x80)
8063  {
8064  s += 1;
8065  }
8066  else
8067  {
8068  s += ImTextCharFromUtf8(&c, s, text_end);
8069  if (c == 0)
8070  break;
8071  }
8072 
8073  if (c == '\n')
8074  {
8075  text_size.x = ImMax(text_size.x, line_width);
8076  text_size.y += line_height;
8077  line_width = 0.0f;
8078  continue;
8079  }
8080 
8081  const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
8082  if (line_width + char_width >= max_width)
8083  break;
8084 
8085  line_width += char_width;
8086  }
8087 
8088  if (line_width > 0 || text_size.y == 0.0f)
8089  {
8090  if (text_size.x < line_width)
8091  text_size.x = line_width;
8092  text_size.y += line_height;
8093  }
8094 
8095  if (remaining)
8096  *remaining = s;
8097 
8098  return text_size;
8099 }
8100 
8101 ImVec2 ImFont::CalcTextSizeW(float size, float max_width, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining) const
8102 {
8103  if (!text_end)
8104  text_end = text_begin + ImStrlenW(text_begin);
8105 
8106  const float scale = size / FontSize;
8107  const float line_height = FontSize * scale;
8108 
8109  ImVec2 text_size = ImVec2(0,0);
8110  float line_width = 0.0f;
8111 
8112  const ImWchar* s = text_begin;
8113  while (s < text_end)
8114  {
8115  const unsigned int c = (unsigned int)(*s++);
8116 
8117  if (c == '\n')
8118  {
8119  text_size.x = ImMax(text_size.x, line_width);
8120  text_size.y += line_height;
8121  line_width = 0.0f;
8122  continue;
8123  }
8124 
8125  const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
8126  if (line_width + char_width >= max_width)
8127  break;
8128 
8129  line_width += char_width;
8130  }
8131 
8132  if (line_width > 0 || text_size.y == 0.0f)
8133  {
8134  if (text_size.x < line_width)
8135  text_size.x = line_width;
8136  text_size.y += line_height;
8137  }
8138 
8139  if (remaining)
8140  *remaining = s;
8141 
8142  return text_size;
8143 }
8144 
8145 void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect_ref, const char* text_begin, const char* text_end, ImDrawVert*& out_vertices, float wrap_width, const ImVec2* cpu_clip_max) const
8146 {
8147  if (!text_end)
8148  text_end = text_begin + strlen(text_begin);
8149 
8150  const float scale = size / FontSize;
8151  const float line_height = FontSize * scale;
8152 
8153  // Align to be pixel perfect
8154  pos.x = (float)(int)pos.x + DisplayOffset.x;
8155  pos.y = (float)(int)pos.y + DisplayOffset.y;
8156 
8157  const bool word_wrap_enabled = (wrap_width > 0.0f);
8158  const char* word_wrap_eol = NULL;
8159 
8160  ImVec4 clip_rect = clip_rect_ref;
8161  if (cpu_clip_max)
8162  {
8163  clip_rect.z = ImMin(clip_rect.z, cpu_clip_max->x);
8164  clip_rect.w = ImMin(clip_rect.w, cpu_clip_max->y);
8165  }
8166  float x = pos.x;
8167  float y = pos.y;
8168 
8169  const char* s = text_begin;
8170  while (s < text_end)
8171  {
8172  if (word_wrap_enabled)
8173  {
8174  // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
8175  if (!word_wrap_eol)
8176  {
8177  word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x));
8178  if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
8179  word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
8180  }
8181 
8182  if (s >= word_wrap_eol)
8183  {
8184  x = pos.x;
8185  y += line_height;
8186  word_wrap_eol = NULL;
8187 
8188  // Wrapping skips upcoming blanks
8189  while (s < text_end)
8190  {
8191  const char c = *s;
8192  if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
8193  }
8194  continue;
8195  }
8196  }
8197 
8198  // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
8199  unsigned int c = (unsigned int)*s;
8200  if (c < 0x80)
8201  {
8202  s += 1;
8203  }
8204  else
8205  {
8206  s += ImTextCharFromUtf8(&c, s, text_end);
8207  if (c == 0)
8208  break;
8209  }
8210 
8211  if (c == '\n')
8212  {
8213  x = pos.x;
8214  y += line_height;
8215  continue;
8216  }
8217 
8218  float char_width = 0.0f;
8219  if (const Glyph* glyph = FindGlyph((unsigned short)c))
8220  {
8221  char_width = glyph->XAdvance * scale;
8222  if (c != ' ' && c != '\t')
8223  {
8224  // Clipping on Y is more likely
8225  float y1 = (float)(y + glyph->YOffset * scale);
8226  float y2 = (float)(y1 + glyph->Height * scale);
8227  if (y1 <= clip_rect.w && y2 >= clip_rect.y)
8228  {
8229  float x1 = (float)(x + glyph->XOffset * scale);
8230  float x2 = (float)(x1 + glyph->Width * scale);
8231  if (x1 <= clip_rect.z && x2 >= clip_rect.x)
8232  {
8233  // Render a character
8234  float u1 = glyph->U0;
8235  float v1 = glyph->V0;
8236  float u2 = glyph->U1;
8237  float v2 = glyph->V1;
8238 
8239  // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quad and in the "max" direction (bottom-right)
8240  if (cpu_clip_max)
8241  {
8242  if (x2 > cpu_clip_max->x)
8243  {
8244  const float clip_tx = (cpu_clip_max->x - x1) / (x2 - x1);
8245  x2 = cpu_clip_max->x;
8246  u2 = u1 + clip_tx * (u2 - u1);
8247  }
8248  if (y2 > cpu_clip_max->y)
8249  {
8250  const float clip_ty = (cpu_clip_max->y - y1) / (y2 - y1);
8251  y2 = cpu_clip_max->y;
8252  v2 = v1 + clip_ty * (v2 - v1);
8253  }
8254  }
8255 
8256  out_vertices[0].pos = ImVec2(x1, y1);
8257  out_vertices[0].uv = ImVec2(u1, v1);
8258  out_vertices[0].col = col;
8259 
8260  out_vertices[1].pos = ImVec2(x2, y1);
8261  out_vertices[1].uv = ImVec2(u2, v1);
8262  out_vertices[1].col = col;
8263 
8264  out_vertices[2].pos = ImVec2(x2, y2);
8265  out_vertices[2].uv = ImVec2(u2, v2);
8266  out_vertices[2].col = col;
8267 
8268  out_vertices[3] = out_vertices[0];
8269  out_vertices[4] = out_vertices[2];
8270 
8271  out_vertices[5].pos = ImVec2(x1, y2);
8272  out_vertices[5].uv = ImVec2(u1, v2);
8273  out_vertices[5].col = col;
8274 
8275  out_vertices += 6;
8276  }
8277  }
8278  }
8279  }
8280 
8281  x += char_width;
8282  }
8283 }
8284 
8285 //-----------------------------------------------------------------------------
8286 // PLATFORM DEPENDANT HELPERS
8287 //-----------------------------------------------------------------------------
8288 
8289 #if defined(_MSC_VER) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS)
8290 
8291 #ifndef _WINDOWS_
8292 #define WIN32_LEAN_AND_MEAN
8293 #include <windows.h>
8294 #endif
8295 
8296 // Win32 API clipboard implementation
8297 static const char* GetClipboardTextFn_DefaultImpl()
8298 {
8299  static char* buf_local = NULL;
8300  if (buf_local)
8301  {
8302  ImGui::MemFree(buf_local);
8303  buf_local = NULL;
8304  }
8305  if (!OpenClipboard(NULL))
8306  return NULL;
8307  HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT);
8308  if (wbuf_handle == NULL)
8309  return NULL;
8310  if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle))
8311  {
8312  int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
8313  buf_local = (char*)ImGui::MemAlloc(buf_len * sizeof(char));
8314  ImTextStrToUtf8(buf_local, buf_len, wbuf_global, NULL);
8315  }
8316  GlobalUnlock(wbuf_handle);
8317  CloseClipboard();
8318  return buf_local;
8319 }
8320 
8321 // Win32 API clipboard implementation
8322 static void SetClipboardTextFn_DefaultImpl(const char* text)
8323 {
8324  if (!OpenClipboard(NULL))
8325  return;
8326 
8327  const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
8328  HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
8329  if (wbuf_handle == NULL)
8330  return;
8331  ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle);
8332  ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
8333  GlobalUnlock(wbuf_handle);
8334  EmptyClipboard();
8335  SetClipboardData(CF_UNICODETEXT, wbuf_handle);
8336  CloseClipboard();
8337 }
8338 
8339 #else
8340 
8341 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
8343 {
8344  return GImGui->PrivateClipboard;
8345 }
8346 
8347 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
8348 static void SetClipboardTextFn_DefaultImpl(const char* text)
8349 {
8350  ImGuiState& g = *GImGui;
8351  if (g.PrivateClipboard)
8352  {
8353  ImGui::MemFree(g.PrivateClipboard);
8354  g.PrivateClipboard = NULL;
8355  }
8356  const char* text_end = text + strlen(text);
8357  g.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1);
8358  memcpy(g.PrivateClipboard, text, (size_t)(text_end - text));
8359  g.PrivateClipboard[(size_t)(text_end - text)] = 0;
8360 }
8361 
8362 #endif
8363 
8364 #if defined(_MSC_VER) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)
8365 
8366 #ifndef _WINDOWS_
8367 #define WIN32_LEAN_AND_MEAN
8368 #include <windows.h>
8369 #endif
8370 #include <Imm.h>
8371 #pragma comment(lib, "imm32")
8372 
8373 static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
8374 {
8375  // Notify OS Input Method Editor of text input position
8376  if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)
8377  if (HIMC himc = ImmGetContext(hwnd))
8378  {
8379  COMPOSITIONFORM cf;
8380  cf.ptCurrentPos.x = x;
8381  cf.ptCurrentPos.y = y;
8382  cf.dwStyle = CFS_FORCE_POSITION;
8383  ImmSetCompositionWindow(himc, &cf);
8384  }
8385 }
8386 
8387 #else
8388 
8389 static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
8390 {
8391 }
8392 
8393 #endif
8394 
8395 //-----------------------------------------------------------------------------
8396 // HELP
8397 //-----------------------------------------------------------------------------
8398 
8400 {
8401  ImGuiState& g = *GImGui;
8402 
8403  ImGui::BulletText("Double-click on title bar to collapse window.");
8404  ImGui::BulletText("Click and drag on lower right corner to resize window.");
8405  ImGui::BulletText("Click and drag on any empty space to move window.");
8406  ImGui::BulletText("Mouse Wheel to scroll.");
8407  if (g.IO.FontAllowUserScaling)
8408  ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
8409  ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
8410  ImGui::BulletText("CTRL+Click on a slider to input text.");
8412  "While editing text:\n"
8413  "- Hold SHIFT or use mouse to select text\n"
8414  "- CTRL+Left/Right to word jump\n"
8415  "- CTRL+A select all\n"
8416  "- CTRL+X,CTRL+C,CTRL+V clipboard\n"
8417  "- CTRL+Z,CTRL+Y undo/redo\n"
8418  "- ESCAPE to revert\n"
8419  "- You can apply arithmetic operators +,*,/ on numerical values.\n"
8420  " Use +- to subtract.\n");
8421 }
8422 
8424 {
8425  ImGuiState& g = *GImGui;
8426  ImGuiStyle& style = g.Style;
8427 
8428  const ImGuiStyle def; // Default style
8429 
8430  if (ImGui::Button("Revert Style"))
8431  g.Style = ref ? *ref : def;
8432  if (ref)
8433  {
8434  ImGui::SameLine();
8435  if (ImGui::Button("Save Style"))
8436  *ref = g.Style;
8437  }
8438 
8440 
8441  if (ImGui::TreeNode("Sizes"))
8442  {
8443  ImGui::SliderFloat("Alpha", &style.Alpha, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI. But application code could have a toggle to switch between zero and non-zero.
8444  ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
8445  ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 16.0f, "%.0f");
8446  ImGui::SliderFloat("ChildWindowRounding", &style.ChildWindowRounding, 0.0f, 16.0f, "%.0f");
8447  ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
8448  ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 16.0f, "%.0f");
8449  ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
8450  ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
8451  ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
8452  ImGui::SliderFloat("TreeNodeSpacing", &style.TreeNodeSpacing, 0.0f, 20.0f, "%.0f");
8453  ImGui::SliderFloat("ScrollBarWidth", &style.ScrollbarWidth, 1.0f, 20.0f, "%.0f");
8454  ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
8455  ImGui::TreePop();
8456  }
8457 
8458  if (ImGui::TreeNode("Colors"))
8459  {
8460  static int output_dest = 0;
8461  static bool output_only_modified = false;
8462  if (ImGui::Button("Output Colors"))
8463  {
8464  if (output_dest == 0)
8466  else
8467  ImGui::LogToTTY();
8468  ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" STR_NEWLINE);
8469  for (int i = 0; i < ImGuiCol_COUNT; i++)
8470  {
8471  const ImVec4& col = style.Colors[i];
8472  const char* name = ImGui::GetStyleColName(i);
8473  if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0)
8474  ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" STR_NEWLINE, name, 22 - strlen(name), "", col.x, col.y, col.z, col.w);
8475  }
8476  ImGui::LogFinish();
8477  }
8478  ImGui::SameLine(); ImGui::PushItemWidth(150); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY"); ImGui::PopItemWidth();
8479  ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified);
8480 
8481  static ImGuiColorEditMode edit_mode = ImGuiColorEditMode_RGB;
8482  ImGui::RadioButton("RGB", &edit_mode, ImGuiColorEditMode_RGB);
8483  ImGui::SameLine();
8484  ImGui::RadioButton("HSV", &edit_mode, ImGuiColorEditMode_HSV);
8485  ImGui::SameLine();
8486  ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX);
8487  //ImGui::Text("Tip: Click on colored square to change edit mode.");
8488 
8489  static ImGuiTextFilter filter;
8490  filter.Draw("Filter colors", 200);
8491 
8492  ImGui::BeginChild("#colors", ImVec2(0, 300), true);
8493 
8494  ImGui::ColorEditMode(edit_mode);
8495  for (int i = 0; i < ImGuiCol_COUNT; i++)
8496  {
8497  const char* name = ImGui::GetStyleColName(i);
8498  if (!filter.PassFilter(name))
8499  continue;
8500  ImGui::PushID(i);
8501  ImGui::ColorEdit4(name, (float*)&style.Colors[i], true);
8502  if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0)
8503  {
8504  ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i];
8505  if (ref) { ImGui::SameLine(); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; }
8506  }
8507  ImGui::PopID();
8508  }
8509  ImGui::EndChild();
8510 
8511  ImGui::TreePop();
8512  }
8513 
8515 }
8516 
8517 //-----------------------------------------------------------------------------
8518 // SAMPLE CODE
8519 //-----------------------------------------------------------------------------
8520 
8521 static void ShowExampleAppConsole(bool* opened);
8522 static void ShowExampleAppLongText(bool* opened);
8523 static void ShowExampleAppAutoResize(bool* opened);
8524 static void ShowExampleAppFixedOverlay(bool* opened);
8525 static void ShowExampleAppManipulatingWindowTitle(bool* opened);
8526 static void ShowExampleAppCustomRendering(bool* opened);
8527 
8528 // Demonstrate ImGui features (unfortunately this makes this function a little bloated!)
8529 void ImGui::ShowTestWindow(bool* opened)
8530 {
8531  // Examples apps
8532  static bool show_app_console = false;
8533  static bool show_app_long_text = false;
8534  static bool show_app_auto_resize = false;
8535  static bool show_app_fixed_overlay = false;
8536  static bool show_app_custom_rendering = false;
8537  static bool show_app_manipulating_window_title = false;
8538  if (show_app_console)
8539  ShowExampleAppConsole(&show_app_console);
8540  if (show_app_long_text)
8541  ShowExampleAppLongText(&show_app_long_text);
8542  if (show_app_auto_resize)
8543  ShowExampleAppAutoResize(&show_app_auto_resize);
8544  if (show_app_fixed_overlay)
8545  ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
8546  if (show_app_manipulating_window_title)
8547  ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);
8548  if (show_app_custom_rendering)
8549  ShowExampleAppCustomRendering(&show_app_custom_rendering);
8550 
8551  static bool no_titlebar = false;
8552  static bool no_border = true;
8553  static bool no_resize = false;
8554  static bool no_move = false;
8555  static bool no_scrollbar = false;
8556  static bool no_collapse = false;
8557  static float bg_alpha = 0.65f;
8558 
8559  // Demonstrate the various window flags. Typically you would just use the default.
8560  ImGuiWindowFlags window_flags = 0;
8561  if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
8562  if (!no_border) window_flags |= ImGuiWindowFlags_ShowBorders;
8563  if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
8564  if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
8565  if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
8566  if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
8567  if (!ImGui::Begin("ImGui Test", opened, ImVec2(550,680), bg_alpha, window_flags))
8568  {
8569  // Early out if the window is collapsed, as an optimization.
8570  ImGui::End();
8571  return;
8572  }
8573 
8574  ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels
8575  //ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels
8576 
8577  ImGui::Text("ImGui says hello.");
8578  //ImGui::Text("MousePos (%g, %g)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
8579  //ImGui::Text("MouseWheel %d", ImGui::GetIO().MouseWheel);
8580  //ImGui::Text("WantCaptureMouse: %d", ImGui::GetIO().WantCaptureMouse);
8581  //ImGui::Text("WantCaptureKeyboard: %d", ImGui::GetIO().WantCaptureKeyboard);
8582 
8583  ImGui::Spacing();
8584  if (ImGui::CollapsingHeader("Help"))
8585  {
8586  ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\n\nUser Guide:");
8588  }
8589 
8590  if (ImGui::CollapsingHeader("Window options"))
8591  {
8592  ImGui::Checkbox("no titlebar", &no_titlebar); ImGui::SameLine(150);
8593  ImGui::Checkbox("no border", &no_border); ImGui::SameLine(300);
8594  ImGui::Checkbox("no resize", &no_resize);
8595  ImGui::Checkbox("no move", &no_move); ImGui::SameLine(150);
8596  ImGui::Checkbox("no scrollbar", &no_scrollbar); ImGui::SameLine(300);
8597  ImGui::Checkbox("no collapse", &no_collapse);
8598  ImGui::SliderFloat("bg alpha", &bg_alpha, 0.0f, 1.0f);
8599 
8600  if (ImGui::TreeNode("Style"))
8601  {
8603  ImGui::TreePop();
8604  }
8605 
8606  if (ImGui::TreeNode("Fonts"))
8607  {
8608  ImGui::TextWrapped("Tip: Load fonts with GetIO().Fonts->AddFontFromFileTTF().");
8609  for (size_t i = 0; i < ImGui::GetIO().Fonts->Fonts.size(); i++)
8610  {
8611  ImFont* font = ImGui::GetIO().Fonts->Fonts[i];
8612  ImGui::BulletText("Font %d: %.2f pixels, %d glyphs", i, font->FontSize, font->Glyphs.size());
8613  ImGui::TreePush((void*)i);
8614  ImGui::PushFont(font);
8615  ImGui::Text("The quick brown fox jumps over the lazy dog");
8616  ImGui::PopFont();
8617  if (i > 0 && ImGui::Button("Set as default"))
8618  {
8620  ImGui::GetIO().Fonts->Fonts[0] = font;
8621  }
8622  ImGui::SliderFloat("font scale", &font->Scale, 0.3f, 2.0f, "%.1f"); // scale only this font
8623  ImGui::TreePop();
8624  }
8625  static float window_scale = 1.0f;
8626  ImGui::SliderFloat("this window scale", &window_scale, 0.3f, 2.0f, "%.1f"); // scale only this window
8627  ImGui::SliderFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.3f, 2.0f, "%.1f"); // scale everything
8628  ImGui::SetWindowFontScale(window_scale);
8629  ImGui::TreePop();
8630  }
8631 
8632  if (ImGui::TreeNode("Logging"))
8633  {
8635  ImGui::TreePop();
8636  }
8637  }
8638 
8639  if (ImGui::CollapsingHeader("Widgets"))
8640  {
8641  static bool a=false;
8642  if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; }
8643  if (a)
8644  {
8645  ImGui::SameLine();
8646  ImGui::Text("Thanks for clicking me!");
8647  }
8648 
8649  if (ImGui::TreeNode("Tree"))
8650  {
8651  for (size_t i = 0; i < 5; i++)
8652  {
8653  if (ImGui::TreeNode((void*)i, "Child %d", i))
8654  {
8655  ImGui::Text("blah blah");
8656  ImGui::SameLine();
8657  if (ImGui::SmallButton("print"))
8658  printf("Child %d pressed", (int)i);
8659  ImGui::TreePop();
8660  }
8661  }
8662  ImGui::TreePop();
8663  }
8664 
8665  if (ImGui::TreeNode("Bullets"))
8666  {
8667  ImGui::BulletText("Bullet point 1");
8668  ImGui::BulletText("Bullet point 2\nOn multiple lines");
8669  ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
8670  ImGui::Bullet(); ImGui::SmallButton("Button 1");
8671  ImGui::Bullet(); ImGui::SmallButton("Button 2");
8672  ImGui::TreePop();
8673  }
8674 
8675  if (ImGui::TreeNode("Colored Text"))
8676  {
8677  // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
8678  ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
8679  ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
8680  ImGui::TreePop();
8681  }
8682 
8683  if (ImGui::TreeNode("Word Wrapping"))
8684  {
8685  // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
8686  ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules that works for English and possibly other languages.");
8687  ImGui::Spacing();
8688 
8689  static float wrap_width = 200.0f;
8690  ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
8691 
8692  ImGui::Text("Test paragraph 1:");
8694  ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
8695  ImGui::Text("lazy dog. This paragraph is made to fit within %.0f pixels. The quick brown fox jumps over the lazy dog.", wrap_width);
8698 
8699  ImGui::Text("Test paragraph 2:");
8701  ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
8702  ImGui::Text("aaaaaaaa bbbbbbbb, cccccccc,dddddddd. eeeeeeee ffffffff. gggggggg!hhhhhhhh");
8705 
8706  ImGui::TreePop();
8707  }
8708 
8709  if (ImGui::TreeNode("UTF-8 Text"))
8710  {
8711  // UTF-8 test with Japanese characters
8712  // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)
8713  // Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature')
8714  // However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants.
8715  // In your own application be reasonable and use UTF-8 in source or retrieve the data from file system!
8716  // Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
8717  ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
8718  ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
8719  ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
8720  static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
8721  ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
8722  ImGui::TreePop();
8723  }
8724 
8725  if (ImGui::TreeNode("Clipping"))
8726  {
8727  static ImVec2 size(80, 20);
8728  ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text if it won't fit in its frame.");
8729  ImGui::SliderFloat2("size", (float*)&size, 5.0f, 200.0f);
8730  ImGui::Button("Line 1 hello\nLine 2 clip me!", size);
8731  ImGui::TextWrapped("Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and rendering cost.");
8732  ImGui::TreePop();
8733  }
8734 
8735  if (ImGui::TreeNode("Images"))
8736  {
8737  ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
8738  ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos();
8739  float tex_w = (float)ImGui::GetIO().Fonts->TexWidth;
8740  float tex_h = (float)ImGui::GetIO().Fonts->TexHeight;
8741  ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;
8742  ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
8743  if (ImGui::IsItemHovered())
8744  {
8746  float focus_sz = 32.0f;
8747  float focus_x = ImClamp(ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f, 0.0f, tex_w - focus_sz);
8748  float focus_y = ImClamp(ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f, 0.0f, tex_h - focus_sz);
8749  ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y);
8750  ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
8751  ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h);
8752  ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h);
8753  ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
8755  }
8756  ImGui::TextWrapped("And now some textured buttons..");
8757  static int pressed_count = 0;
8758  for (int i = 0; i < 8; i++)
8759  {
8760  if (i > 0)
8761  ImGui::SameLine();
8762  ImGui::PushID(i);
8763  int frame_padding = -1 + i; // -1 padding uses default padding
8764  if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding))
8765  pressed_count += 1;
8766  ImGui::PopID();
8767  }
8768  ImGui::Text("Pressed %d times.", pressed_count);
8769  ImGui::TreePop();
8770  }
8771 
8772  if (ImGui::TreeNode("Selectables"))
8773  {
8774  if (ImGui::TreeNode("Basic"))
8775  {
8776  static bool selected[3] = { false, true, false };
8777  ImGui::Selectable("1. I am selectable", &selected[0]);
8778  ImGui::Selectable("2. I am selectable", &selected[1]);
8779  ImGui::Text("3. I am normal text");
8780  ImGui::Selectable("4. I am selectable", &selected[2]);
8781  ImGui::TreePop();
8782  }
8783  if (ImGui::TreeNode("Rendering more text into the same block"))
8784  {
8785  static bool selected[3] = { false, false, false };
8786  ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
8787  ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
8788  ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
8789  ImGui::TreePop();
8790  }
8791  if (ImGui::TreeNode("Grid"))
8792  {
8793  static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
8794  for (int i = 0; i < 16; i++)
8795  {
8796  ImGui::PushID(i);
8797  if (ImGui::Selectable("Me", &selected[i], ImVec2(50,50)))
8798  {
8799  int x = i % 4, y = i / 4;
8800  if (x > 0) selected[i - 1] ^= 1;
8801  if (x < 3) selected[i + 1] ^= 1;
8802  if (y > 0) selected[i - 4] ^= 1;
8803  if (y < 3) selected[i + 4] ^= 1;
8804  }
8805  if ((i % 4) < 3) ImGui::SameLine();
8806  ImGui::PopID();
8807  }
8808  ImGui::TreePop();
8809  }
8810  ImGui::TreePop();
8811  }
8812 
8813  if (ImGui::TreeNode("Filtered Text Input"))
8814  {
8815  static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
8816  static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
8817  static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
8818  static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
8819  static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
8820  struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
8821  static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
8822  ImGui::TreePop();
8823  }
8824 
8825  static bool check = true;
8826  ImGui::Checkbox("checkbox", &check);
8827 
8828  static int e = 0;
8829  ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
8830  ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
8831  ImGui::RadioButton("radio c", &e, 2);
8832 
8833  // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
8834  for (int i = 0; i < 7; i++)
8835  {
8836  if (i > 0) ImGui::SameLine();
8837  ImGui::PushID(i);
8838  ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f));
8841  ImGui::Button("Click");
8843  ImGui::PopID();
8844  }
8845 
8846  ImGui::Text("Hover over me");
8847  if (ImGui::IsItemHovered())
8848  ImGui::SetTooltip("I am a tooltip");
8849 
8850  ImGui::SameLine();
8851  ImGui::Text("- or me");
8852  if (ImGui::IsItemHovered())
8853  {
8855  ImGui::Text("I am a fancy tooltip");
8856  static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
8857  ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
8859  }
8860 
8861  // Testing IMGUI_ONCE_UPON_A_FRAME macro
8862  //for (int i = 0; i < 5; i++)
8863  //{
8864  // IMGUI_ONCE_UPON_A_FRAME
8865  // {
8866  // ImGui::Text("This will be displayed only once.");
8867  // }
8868  //}
8869 
8870  ImGui::Separator();
8871 
8872  static int item = 1;
8873  ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
8874 
8875  const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" };
8876  static int item2 = -1;
8877  ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items));
8878 
8879  static char str0[128] = "Hello, world!";
8880  static int i0=123;
8881  static float f0=0.001f;
8882  ImGui::InputText("string", str0, IM_ARRAYSIZE(str0));
8883  ImGui::InputInt("input int", &i0);
8884  ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
8885 
8886  static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
8887  //ImGui::InputFloat2("input float2", vec4a);
8888  ImGui::InputFloat3("input float3", vec4a);
8889  //ImGui::InputFloat4("input float4", vec4a);
8890 
8891  static int i1=0;
8892  static int i2=42;
8893  ImGui::SliderInt("int 0..3", &i1, 0, 3);
8894  ImGui::SliderInt("int -100..100", &i2, -100, 100);
8895 
8896  static float f1=1.123f;
8897  static float f2=0;
8898  static float f3=0;
8899  static float f4=123456789.0f;
8900  ImGui::SliderFloat("float", &f1, 0.0f, 2.0f);
8901  ImGui::SliderFloat("log float", &f2, 0.0f, 10.0f, "%.4f", 2.0f);
8902  ImGui::SliderFloat("signed log float", &f3, -10.0f, 10.0f, "%.4f", 3.0f);
8903  ImGui::SliderFloat("unbound float", &f4, -FLT_MAX, FLT_MAX, "%.4f");
8904  static float angle = 0.0f;
8905  ImGui::SliderAngle("angle", &angle);
8906 
8907  static float vec4b[4] = { 0.10f, 0.20f, 0.30f, 0.40f };
8908  //ImGui::SliderFloat2("slider float2", vec4b, 0.0f, 1.0f);
8909  ImGui::SliderFloat3("slider float3", vec4b, 0.0f, 1.0f);
8910  //ImGui::SliderFloat4("slider float4", vec4b, 0.0f, 1.0f);
8911 
8912  //static int vec4i[4] = { 1, 5, 100, 255 };
8913  //ImGui::SliderInt2("slider int2", vec4i, 0, 255);
8914  //ImGui::SliderInt3("slider int3", vec4i, 0, 255);
8915  //ImGui::SliderInt4("slider int4", vec4i, 0, 255);
8916 
8917  static float col1[3] = { 1.0f,0.0f,0.2f };
8918  static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
8919  ImGui::ColorEdit3("color 1", col1);
8920  ImGui::ColorEdit4("color 2", col2);
8921 
8922  const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
8923  static int listbox_item_current = 1;
8924  ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
8925 
8926  //static int listbox_item_current2 = 2;
8927  //ImGui::PushItemWidth(-1);
8928  //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
8929  //ImGui::PopItemWidth();
8930  }
8931 
8932  if (ImGui::CollapsingHeader("Graphs widgets"))
8933  {
8934  static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
8935  ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
8936 
8937  static bool pause;
8938  static ImVector<float> values; if (values.empty()) { values.resize(100); memset(&values.front(), 0, values.size()*sizeof(float)); }
8939  static size_t values_offset = 0;
8940  if (!pause)
8941  {
8942  // create dummy data at fixed 60 hz rate
8943  static float refresh_time = -1.0f;
8944  if (ImGui::GetTime() > refresh_time + 1.0f/60.0f)
8945  {
8946  refresh_time = ImGui::GetTime();
8947  static float phase = 0.0f;
8948  values[values_offset] = cosf(phase);
8949  values_offset = (values_offset+1)%values.size();
8950  phase += 0.10f*values_offset;
8951  }
8952  }
8953  ImGui::PlotLines("Frame Times", &values.front(), (int)values.size(), (int)values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,70));
8954 
8955  ImGui::SameLine(); ImGui::Checkbox("pause", &pause);
8956  ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,70));
8957  }
8958 
8959  if (ImGui::CollapsingHeader("Horizontal Layout"))
8960  {
8961  // Text
8962  ImGui::Text("Hello");
8963  ImGui::SameLine();
8964  ImGui::Text("World");
8965 
8966  // Button
8967  if (ImGui::Button("Banana")) printf("Pressed!\n");
8968  ImGui::SameLine();
8969  ImGui::Button("Apple");
8970  ImGui::SameLine();
8971  ImGui::Button("Corniflower");
8972 
8973  // Button
8974  ImGui::Text("Small buttons");
8975  ImGui::SameLine();
8976  ImGui::SmallButton("Like this one");
8977  ImGui::SameLine();
8978  ImGui::Text("can fit within a text block.");
8979 
8980  // Checkbox
8981  static bool c1=false,c2=false,c3=false,c4=false;
8982  ImGui::Checkbox("My", &c1);
8983  ImGui::SameLine();
8984  ImGui::Checkbox("Tailor", &c2);
8985  ImGui::SameLine();
8986  ImGui::Checkbox("Is", &c3);
8987  ImGui::SameLine();
8988  ImGui::Checkbox("Rich", &c4);
8989 
8990  // Various
8991  static float f0=1.0f, f1=2.0f, f2=3.0f;
8993  const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
8994  static int item = -1;
8995  ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items));
8996  ImGui::SameLine();
8997  ImGui::SliderFloat("X", &f0, 0.0f,5.0f);
8998  ImGui::SameLine();
8999  ImGui::SliderFloat("Y", &f1, 0.0f,5.0f);
9000  ImGui::SameLine();
9001  ImGui::SliderFloat("Z", &f2, 0.0f,5.0f);
9003 
9005  ImGui::Text("Lists:");
9006  static int selection[4] = { 0, 1, 2, 3 };
9007  for (int i = 0; i < 4; i++)
9008  {
9009  if (i > 0) ImGui::SameLine();
9010  ImGui::PushID(i);
9011  ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
9012  ImGui::PopID();
9013  //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
9014  }
9016  }
9017 
9018  if (ImGui::CollapsingHeader("Child regions"))
9019  {
9020  ImGui::Text("Without border");
9021  static int line = 50;
9022  bool goto_line = ImGui::Button("Goto");
9023  ImGui::SameLine();
9024  ImGui::PushItemWidth(100);
9025  goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
9027  ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowWidth() * 0.5f,300));
9028  for (int i = 0; i < 100; i++)
9029  {
9030  ImGui::Text("%04d: scrollable region", i);
9031  if (goto_line && line == i)
9033  }
9034  if (goto_line && line >= 100)
9036  ImGui::EndChild();
9037 
9038  ImGui::SameLine();
9039 
9041  ImGui::BeginChild("Sub2", ImVec2(0,300), true);
9042  ImGui::Text("With border");
9043  ImGui::Columns(2);
9044  for (int i = 0; i < 100; i++)
9045  {
9046  if (i == 50)
9048  char buf[32];
9049  ImFormatString(buf, IM_ARRAYSIZE(buf), "%08x", i*5731);
9050  ImGui::Button(buf);
9051  }
9052  ImGui::EndChild();
9054  }
9055 
9056  if (ImGui::CollapsingHeader("Columns"))
9057  {
9058  // Basic columns
9059  ImGui::Text("Basic:");
9060  ImGui::Columns(4, "mycolumns");
9061  ImGui::Text("ID"); ImGui::NextColumn();
9062  ImGui::Text("Name"); ImGui::NextColumn();
9063  ImGui::Text("Path"); ImGui::NextColumn();
9064  ImGui::Text("Flags"); ImGui::NextColumn();
9065  ImGui::Separator();
9066  const char* names[3] = { "Robert", "Stephanie", "C64" };
9067  const char* paths[3] = { "/path/robert", "/path/stephanie", "/path/computer" };
9068  for (int i = 0; i < 3; i++)
9069  {
9070  ImGui::Text("%04d", i); ImGui::NextColumn();
9071  ImGui::Text(names[i]); ImGui::NextColumn();
9072  ImGui::Text(paths[i]); ImGui::NextColumn();
9073  ImGui::Text("...."); ImGui::NextColumn();
9074  }
9075  ImGui::Columns(1);
9076 
9077  ImGui::Separator();
9078  ImGui::Spacing();
9079 
9080  // Scrolling columns
9081  /*
9082  ImGui::Text("Scrolling:");
9083  ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
9084  ImGui::Columns(3);
9085  ImGui::Text("ID"); ImGui::NextColumn();
9086  ImGui::Text("Name"); ImGui::NextColumn();
9087  ImGui::Text("Path"); ImGui::NextColumn();
9088  ImGui::Columns(1);
9089  ImGui::Separator();
9090  ImGui::EndChild();
9091  ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
9092  ImGui::Columns(3);
9093  for (int i = 0; i < 10; i++)
9094  {
9095  ImGui::Text("%04d", i); ImGui::NextColumn();
9096  ImGui::Text("Foobar"); ImGui::NextColumn();
9097  ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
9098  }
9099  ImGui::Columns(1);
9100  ImGui::EndChild();
9101 
9102  ImGui::Separator();
9103  ImGui::Spacing();
9104  */
9105 
9106  // Create multiple items in a same cell before switching to next column
9107  ImGui::Text("Mixed items:");
9108  ImGui::Columns(3, "mixed");
9109  ImGui::Separator();
9110 
9111  static int e = 0;
9112  ImGui::Text("Hello");
9113  ImGui::Button("Banana");
9114  ImGui::RadioButton("radio a", &e, 0);
9116 
9117  ImGui::Text("ImGui");
9118  ImGui::Button("Apple");
9119  ImGui::RadioButton("radio b", &e, 1);
9120  static float foo = 1.0f;
9121  ImGui::InputFloat("red", &foo, 0.05f, 0, 3);
9122  ImGui::Text("An extra line here.");
9124 
9125  ImGui::Text("World!");
9126  ImGui::Button("Corniflower");
9127  ImGui::RadioButton("radio c", &e, 2);
9128  static float bar = 1.0f;
9129  ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
9131 
9132  if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
9133  if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
9134  if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
9135  ImGui::Columns(1);
9136 
9137  ImGui::Separator();
9138  ImGui::Spacing();
9139 
9140  // Tree items
9141  ImGui::Text("Tree items:");
9142  ImGui::Columns(2, "tree items");
9143  ImGui::Separator();
9144  if (ImGui::TreeNode("Hello")) { ImGui::BulletText("World"); ImGui::TreePop(); } ImGui::NextColumn();
9145  if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Monde"); ImGui::TreePop(); } ImGui::NextColumn();
9146  ImGui::Columns(1);
9147 
9148  ImGui::Separator();
9149  ImGui::Spacing();
9150 
9151  // Word-wrapping
9152  ImGui::Text("Word-wrapping:");
9153  ImGui::Columns(2, "word-wrapping");
9154  ImGui::Separator();
9155  ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
9156  ImGui::Text("Hello Left");
9158  ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
9159  ImGui::Text("Hello Right");
9160  ImGui::Columns(1);
9161 
9162  ImGui::Separator();
9163  ImGui::Spacing();
9164 
9165  if (ImGui::TreeNode("Inside a tree.."))
9166  {
9167  if (ImGui::TreeNode("node 1 (with borders)"))
9168  {
9169  ImGui::Columns(4);
9170  for (int i = 0; i < 8; i++)
9171  {
9172  ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
9174  }
9175  ImGui::Columns(1);
9176  ImGui::TreePop();
9177  }
9178  if (ImGui::TreeNode("node 2 (without borders)"))
9179  {
9180  ImGui::Columns(4, NULL, false);
9181  for (int i = 0; i < 8; i++)
9182  {
9183  ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
9185  }
9186  ImGui::Columns(1);
9187  ImGui::TreePop();
9188  }
9189  ImGui::TreePop();
9190  }
9191  }
9192 
9193  if (ImGui::CollapsingHeader("Filtering"))
9194  {
9195  static ImGuiTextFilter filter;
9196  ImGui::Text("Filter usage:\n"
9197  " \"\" display all lines\n"
9198  " \"xxx\" display lines containing \"xxx\"\n"
9199  " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
9200  " \"-xxx\" hide lines containing \"xxx\"");
9201  filter.Draw();
9202  const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
9203  for (size_t i = 0; i < IM_ARRAYSIZE(lines); i++)
9204  if (filter.PassFilter(lines[i]))
9205  ImGui::BulletText("%s", lines[i]);
9206  }
9207 
9208  if (ImGui::CollapsingHeader("Keyboard & Focus"))
9209  {
9210  if (ImGui::TreeNode("Tabbing"))
9211  {
9212  ImGui::Text("Use TAB/SHIFT+TAB to cycle thru keyboard editable fields.");
9213  static char buf[32] = "dummy";
9214  ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
9215  ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
9216  ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
9218  ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
9219  //ImGui::SameLine(); ImGui::Text("(?)"); if (ImGui::IsHovered()) ImGui::SetTooltip("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
9221  ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
9222  ImGui::TreePop();
9223  }
9224 
9225  if (ImGui::TreeNode("Focus from code"))
9226  {
9227  bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
9228  bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
9229  bool focus_3 = ImGui::Button("Focus on 3");
9230  int has_focus = 0;
9231  static char buf[128] = "click on a button to set focus";
9232 
9233  if (focus_1) ImGui::SetKeyboardFocusHere();
9234  ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
9235  if (ImGui::IsItemActive()) has_focus = 1;
9236 
9237  if (focus_2) ImGui::SetKeyboardFocusHere();
9238  ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
9239  if (ImGui::IsItemActive()) has_focus = 2;
9240 
9242  if (focus_3) ImGui::SetKeyboardFocusHere();
9243  ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
9244  if (ImGui::IsItemActive()) has_focus = 3;
9246  if (has_focus)
9247  ImGui::Text("Item with focus: %d", has_focus);
9248  else
9249  ImGui::Text("Item with focus: <none>");
9250  ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
9251  ImGui::TreePop();
9252  }
9253  }
9254 
9255  if (ImGui::CollapsingHeader("App Examples"))
9256  {
9257  ImGui::Checkbox("Console", &show_app_console);
9258  ImGui::Checkbox("Long text display", &show_app_long_text);
9259  ImGui::Checkbox("Auto-resizing window", &show_app_auto_resize);
9260  ImGui::Checkbox("Simple overlay", &show_app_fixed_overlay);
9261  ImGui::Checkbox("Manipulating window title", &show_app_manipulating_window_title);
9262  ImGui::Checkbox("Custom rendering", &show_app_custom_rendering);
9263  }
9264 
9265  ImGui::End();
9266 }
9267 
9268 static void ShowExampleAppAutoResize(bool* opened)
9269 {
9270  if (!ImGui::Begin("Example: Auto-Resizing Window", opened, ImVec2(0,0), -1.0f, ImGuiWindowFlags_AlwaysAutoResize))
9271  {
9272  ImGui::End();
9273  return;
9274  }
9275 
9276  static int lines = 10;
9277  ImGui::TextWrapped("Window will resize every-frame to the size of its content. Note that you don't want to query the window size to output your content because that would create a feedback loop.");
9278  ImGui::SliderInt("Number of lines", &lines, 1, 20);
9279  for (int i = 0; i < lines; i++)
9280  ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally
9281 
9282  ImGui::End();
9283 }
9284 
9285 static void ShowExampleAppFixedOverlay(bool* opened)
9286 {
9288  {
9289  ImGui::End();
9290  return;
9291  }
9292 
9293  ImGui::SetWindowPos(ImVec2(10,10));
9294  ImGui::Text("Simple overlay\non the top-left side of the screen.");
9295  ImGui::Separator();
9296  ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
9297 
9298  ImGui::End();
9299 }
9300 
9301 static void ShowExampleAppManipulatingWindowTitle(bool* opened)
9302 {
9303  (void)opened;
9304 
9305  // By default, Windows are uniquely identified by their title.
9306  // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file!
9307 
9308  // Using "##" to display same title but have unique identifier.
9310  ImGui::Begin("Same title as another window##1");
9311  ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
9312  ImGui::End();
9313 
9315  ImGui::Begin("Same title as another window##2");
9316  ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
9317  ImGui::End();
9318 
9319  // Using "###" to display a changing title but keep a static identifier "MyWindow"
9320  char buf[128];
9321  ImFormatString(buf, IM_ARRAYSIZE(buf), "Animated title %c %d###MyWindow", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand());
9323  ImGui::Begin(buf);
9324  ImGui::Text("This window has a changing title.");
9325  ImGui::End();
9326 }
9327 
9328 static void ShowExampleAppCustomRendering(bool* opened)
9329 {
9331  if (!ImGui::Begin("Example: Custom Rendering", opened))
9332  {
9333  ImGui::End();
9334  return;
9335  }
9336 
9337  // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
9338  // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
9339  // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
9340  // In this example we aren't using the operators.
9341 
9342  static ImVector<ImVec2> points;
9343  static bool adding_line = false;
9344  if (ImGui::Button("Clear")) points.clear();
9345  if (points.size() >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
9346  ImGui::Text("Left-click and drag to add lines");
9347  ImGui::Text("Right-click to undo");
9348 
9349  ImDrawList* draw_list = ImGui::GetWindowDrawList();
9350 
9351  // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
9352  // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
9353  // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
9354  ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
9355  ImVec2 canvas_size = ImVec2(ImMax(50.0f,ImGui::GetWindowContentRegionMax().x-ImGui::GetCursorPos().x), ImMax(50.0f,ImGui::GetWindowContentRegionMax().y-ImGui::GetCursorPos().y)); // Resize canvas what's available
9356  draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), 0xFFFFFFFF);
9357  bool adding_preview = false;
9358  ImGui::InvisibleButton("canvas", canvas_size);
9359  if (ImGui::IsItemHovered())
9360  {
9361  ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
9362  if (!adding_line && ImGui::GetIO().MouseClicked[0])
9363  {
9364  points.push_back(mouse_pos_in_canvas);
9365  adding_line = true;
9366  }
9367  if (adding_line)
9368  {
9369  adding_preview = true;
9370  points.push_back(mouse_pos_in_canvas);
9371  if (!ImGui::GetIO().MouseDown[0])
9372  adding_line = adding_preview = false;
9373  }
9374  if (ImGui::GetIO().MouseClicked[1] && !points.empty())
9375  {
9376  adding_line = false;
9377  points.pop_back();
9378  points.pop_back();
9379  }
9380  }
9381  draw_list->PushClipRect(ImVec4(canvas_pos.x, canvas_pos.y, canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.)
9382  for (int i = 0; i < (int)points.size() - 1; i += 2)
9383  draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), 0xFF00FFFF);
9384  draw_list->PopClipRect();
9385  if (adding_preview)
9386  points.pop_back();
9387  ImGui::End();
9388 }
9389 
9390 struct ExampleAppConsole
9391 {
9392  char InputBuf[256];
9393  ImVector<char*> Items;
9394  bool ScrollToBottom;
9395  ImVector<char*> History;
9396  int HistoryPos; // -1: new line, 0..History.size()-1 browsing history.
9397  ImVector<const char*> Commands;
9398 
9399  ExampleAppConsole()
9400  {
9401  ClearLog();
9402  HistoryPos = -1;
9403  Commands.push_back("HELP");
9404  Commands.push_back("HISTORY");
9405  Commands.push_back("CLEAR");
9406  Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
9407  }
9408  ~ExampleAppConsole()
9409  {
9410  ClearLog();
9411  for (size_t i = 0; i < Items.size(); i++)
9412  ImGui::MemFree(History[i]);
9413  }
9414 
9415  void ClearLog()
9416  {
9417  for (size_t i = 0; i < Items.size(); i++)
9418  ImGui::MemFree(Items[i]);
9419  Items.clear();
9420  ScrollToBottom = true;
9421  }
9422 
9423  void AddLog(const char* fmt, ...)
9424  {
9425  char buf[1024];
9426  va_list args;
9427  va_start(args, fmt);
9428  ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
9429  va_end(args);
9430  Items.push_back(ImStrdup(buf));
9431  ScrollToBottom = true;
9432  }
9433 
9434  void Run(const char* title, bool* opened)
9435  {
9436  if (!ImGui::Begin(title, opened, ImVec2(520,600)))
9437  {
9438  ImGui::End();
9439  return;
9440  }
9441 
9442  ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
9443  ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
9444 
9445  // TODO: display from bottom
9446  // TODO: clip manually
9447 
9448  if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.size()); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
9449  if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine();
9450  if (ImGui::SmallButton("Clear")) ClearLog();
9451  //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
9452 
9453  ImGui::Separator();
9454 
9456  static ImGuiTextFilter filter;
9457  filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
9458  if (ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus on hover
9460  ImGui::Separator();
9461 
9462  // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
9463  // NB- if you have thousands of entries this approach may be too inefficient. You can seek and display only the lines that are visible - CalcListClipping() is a helper to compute this information.
9464  // If your items are of variable size you may want to implement code similar to what CalcListClipping() does. Or split your data into fixed height items to allow random-seeking into your list.
9465  ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetTextLineHeightWithSpacing()*2));
9466  ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
9467  for (size_t i = 0; i < Items.size(); i++)
9468  {
9469  const char* item = Items[i];
9470  if (!filter.PassFilter(item))
9471  continue;
9472  ImVec4 col(1,1,1,1); // A better implement may store a type per-item. For the sample let's just parse the text.
9473  if (strstr(item, "[error]")) col = ImVec4(1.0f,0.4f,0.4f,1.0f);
9474  else if (strncmp(item, "# ", 2) == 0) col = ImVec4(1.0f,0.8f,0.6f,1.0f);
9476  ImGui::TextUnformatted(item);
9478  }
9479  if (ScrollToBottom)
9481  ScrollToBottom = false;
9483  ImGui::EndChild();
9484  ImGui::Separator();
9485 
9486  // Command-line
9488  {
9489  char* input_end = InputBuf+strlen(InputBuf);
9490  while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0;
9491  if (InputBuf[0])
9492  ExecCommand(InputBuf);
9493  strcpy(InputBuf, "");
9494  }
9495 
9496  if (ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus on hover
9497 
9498  ImGui::End();
9499  }
9500 
9501  void ExecCommand(const char* command_line)
9502  {
9503  AddLog("# %s\n", command_line);
9504 
9505  // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
9506  HistoryPos = -1;
9507  for (int i = (int)History.size()-1; i >= 0; i--)
9508  if (ImStricmp(History[i], command_line) == 0)
9509  {
9510  ImGui::MemFree(History[i]);
9511  History.erase(History.begin() + i);
9512  break;
9513  }
9514  History.push_back(ImStrdup(command_line));
9515 
9516  // Process command
9517  if (ImStricmp(command_line, "CLEAR") == 0)
9518  {
9519  ClearLog();
9520  }
9521  else if (ImStricmp(command_line, "HELP") == 0)
9522  {
9523  AddLog("Commands:");
9524  for (size_t i = 0; i < Commands.size(); i++)
9525  AddLog("- %s", Commands[i]);
9526  }
9527  else if (ImStricmp(command_line, "HISTORY") == 0)
9528  {
9529  for (size_t i = History.size() >= 10 ? History.size() - 10 : 0; i < History.size(); i++)
9530  AddLog("%3d: %s\n", i, History[i]);
9531  }
9532  else
9533  {
9534  AddLog("Unknown command: '%s'\n", command_line);
9535  }
9536  }
9537 
9538  static int TextEditCallbackStub(ImGuiTextEditCallbackData* data)
9539  {
9540  ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
9541  return console->TextEditCallback(data);
9542  }
9543 
9544  int TextEditCallback(ImGuiTextEditCallbackData* data)
9545  {
9546  //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
9547  switch (data->EventFlag)
9548  {
9550  {
9551  // Example of TEXT COMPLETION
9552 
9553  // Locate beginning of current word
9554  const char* word_end = data->Buf + data->CursorPos;
9555  const char* word_start = word_end;
9556  while (word_start > data->Buf)
9557  {
9558  const char c = word_start[-1];
9559  if (ImCharIsSpace(c) || c == ',' || c == ';')
9560  break;
9561  word_start--;
9562  }
9563 
9564  // Build a list of candidates
9565  ImVector<const char*> candidates;
9566  for (size_t i = 0; i < Commands.size(); i++)
9567  if (ImStrnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
9568  candidates.push_back(Commands[i]);
9569 
9570  if (candidates.size() == 0)
9571  {
9572  // No match
9573  AddLog("No match for \"%.*s\"!\n", word_end-word_start, word_start);
9574  }
9575  else if (candidates.size() == 1)
9576  {
9577  // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
9578  data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
9579  data->InsertChars(data->CursorPos, candidates[0]);
9580  data->InsertChars(data->CursorPos, " ");
9581  }
9582  else
9583  {
9584  // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
9585  int match_len = (int)(word_end - word_start);
9586  for (;;)
9587  {
9588  int c = 0;
9589  bool all_candidates_matches = true;
9590  for (size_t i = 0; i < candidates.size() && all_candidates_matches; i++)
9591  if (i == 0)
9592  c = toupper(candidates[i][match_len]);
9593  else if (c != toupper(candidates[i][match_len]))
9594  all_candidates_matches = false;
9595  if (!all_candidates_matches)
9596  break;
9597  match_len++;
9598  }
9599 
9600  if (match_len > 0)
9601  {
9602  data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
9603  data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
9604  }
9605 
9606  // List matches
9607  AddLog("Possible matches:\n");
9608  for (size_t i = 0; i < candidates.size(); i++)
9609  AddLog("- %s\n", candidates[i]);
9610  }
9611 
9612  break;
9613  }
9615  {
9616  // Example of HISTORY
9617  const int prev_history_pos = HistoryPos;
9618  if (data->EventKey == ImGuiKey_UpArrow)
9619  {
9620  if (HistoryPos == -1)
9621  HistoryPos = (int)(History.size() - 1);
9622  else if (HistoryPos > 0)
9623  HistoryPos--;
9624  }
9625  else if (data->EventKey == ImGuiKey_DownArrow)
9626  {
9627  if (HistoryPos != -1)
9628  if (++HistoryPos >= (int)History.size())
9629  HistoryPos = -1;
9630  }
9631 
9632  // A better implementation would preserve the data on the current input line along with cursor position.
9633  if (prev_history_pos != HistoryPos)
9634  {
9635  ImFormatString(data->Buf, data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
9636  data->BufDirty = true;
9637  data->CursorPos = data->SelectionStart = data->SelectionEnd = (int)strlen(data->Buf);
9638  }
9639  }
9640  }
9641  return 0;
9642  }
9643 };
9644 
9645 static void ShowExampleAppConsole(bool* opened)
9646 {
9647  static ExampleAppConsole console;
9648  console.Run("Example: Console", opened);
9649 }
9650 
9651 static void ShowExampleAppLongText(bool* opened)
9652 {
9653  if (!ImGui::Begin("Example: Long text display", opened, ImVec2(520,600)))
9654  {
9655  ImGui::End();
9656  return;
9657  }
9658 
9659  static int test_type = 0;
9660  static ImGuiTextBuffer log;
9661  static int lines = 0;
9662  ImGui::Text("Printing unusually long amount of text.");
9663  ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped");
9664  ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
9665  if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
9666  ImGui::SameLine();
9667  if (ImGui::Button("Add 1000 lines"))
9668  {
9669  for (int i = 0; i < 1000; i++)
9670  log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
9671  lines += 1000;
9672  }
9673  ImGui::BeginChild("Log");
9674  switch (test_type)
9675  {
9676  case 0:
9677  // Single call to TextUnformatted() with a big buffer
9678  ImGui::TextUnformatted(log.begin(), log.end());
9679  break;
9680  case 1:
9681  // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the CalcListClipping() helper.
9683  int display_start, display_end;
9684  ImGui::CalcListClipping(lines, ImGui::GetTextLineHeight(), &display_start, &display_end);
9686  for (int i = display_start; i < display_end; i++)
9687  ImGui::Text("%i The quick brown fox jumps over the lazy dog\n", i);
9690  break;
9691  case 2:
9692  // Multiple calls to Text(), not clipped
9694  for (int i = 0; i < lines; i++)
9695  ImGui::Text("%i The quick brown fox jumps over the lazy dog\n", i);
9697  break;
9698  }
9699  ImGui::EndChild();
9700  ImGui::End();
9701 }
9702 
9703 // End of Sample code
9704 
9705 //-----------------------------------------------------------------------------
9706 // FONT DATA
9707 //-----------------------------------------------------------------------------
9708 
9709 //-----------------------------------------------------------------------------
9710 // ProggyClean.ttf
9711 // Copyright (c) 2004, 2005 Tristan Grimmer
9712 // MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
9713 // Download and more information at http://upperbounds.net
9714 //-----------------------------------------------------------------------------
9715 // Compressed with stb_compress() then converted to a C array.
9716 // Decompressor from stb.h (public domain) by Sean Barrett
9717 // https://github.com/nothings/stb/blob/master/stb.h
9718 //-----------------------------------------------------------------------------
9719 
9720 static unsigned int stb_decompress_length(unsigned char *input)
9721 {
9722  return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
9723 }
9724 
9726 
9727 static unsigned char *stb__dout;
9728 static void stb__match(unsigned char *data, unsigned int length)
9729 {
9730  // INVERSE of memmove... write each byte before copying the next...
9731  assert (stb__dout + length <= stb__barrier);
9732  if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
9733  if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }
9734  while (length--) *stb__dout++ = *data++;
9735 }
9736 
9737 static void stb__lit(unsigned char *data, unsigned int length)
9738 {
9739  assert (stb__dout + length <= stb__barrier);
9740  if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
9741  if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
9742  memcpy(stb__dout, data, length);
9743  stb__dout += length;
9744 }
9745 
9746 #define stb__in2(x) ((i[x] << 8) + i[(x)+1])
9747 #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
9748 #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
9749 
9750 static unsigned char *stb_decompress_token(unsigned char *i)
9751 {
9752  if (*i >= 0x20) { // use fewer if's for cases that expand small
9753  if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
9754  else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
9755  else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
9756  } else { // more ifs for cases that expand large, since overhead is amortized
9757  if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
9758  else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
9759  else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
9760  else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
9761  else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
9762  else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
9763  }
9764  return i;
9765 }
9766 
9767 static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
9768 {
9769  const unsigned long ADLER_MOD = 65521;
9770  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
9771  unsigned long blocklen, i;
9772 
9773  blocklen = buflen % 5552;
9774  while (buflen) {
9775  for (i=0; i + 7 < blocklen; i += 8) {
9776  s1 += buffer[0], s2 += s1;
9777  s1 += buffer[1], s2 += s1;
9778  s1 += buffer[2], s2 += s1;
9779  s1 += buffer[3], s2 += s1;
9780  s1 += buffer[4], s2 += s1;
9781  s1 += buffer[5], s2 += s1;
9782  s1 += buffer[6], s2 += s1;
9783  s1 += buffer[7], s2 += s1;
9784 
9785  buffer += 8;
9786  }
9787 
9788  for (; i < blocklen; ++i)
9789  s1 += *buffer++, s2 += s1;
9790 
9791  s1 %= ADLER_MOD, s2 %= ADLER_MOD;
9792  buflen -= blocklen;
9793  blocklen = 5552;
9794  }
9795  return (unsigned int)(s2 << 16) + (unsigned int)s1;
9796 }
9797 
9798 static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length)
9799 {
9800  unsigned int olen;
9801  if (stb__in4(0) != 0x57bC0000) return 0;
9802  if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
9803  olen = stb_decompress_length(i);
9804  stb__barrier2 = i;
9805  stb__barrier3 = i+length;
9806  stb__barrier = output + olen;
9807  stb__barrier4 = output;
9808  i += 16;
9809 
9810  stb__dout = output;
9811  for (;;) {
9812  unsigned char *old_i = i;
9813  i = stb_decompress_token(i);
9814  if (i == old_i) {
9815  if (*i == 0x05 && i[1] == 0xfa) {
9816  assert(stb__dout == output + olen);
9817  if (stb__dout != output + olen) return 0;
9818  if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2))
9819  return 0;
9820  return olen;
9821  } else {
9822  assert(0); /* NOTREACHED */
9823  return 0;
9824  }
9825  }
9826  assert(stb__dout <= output + olen);
9827  if (stb__dout > output + olen)
9828  return 0;
9829  }
9830 }
9831 
9832 static const unsigned int proggy_clean_ttf_compressed_size = 9583;
9833 static const unsigned int proggy_clean_ttf_compressed_data[9584/4] =
9834 {
9835  0x0000bc57, 0x00000000, 0xf8a00000, 0x00000400, 0x00010037, 0x000c0000, 0x00030080, 0x2f534f40, 0x74eb8832, 0x01000090, 0x2c158248, 0x616d634e,
9836  0x23120270, 0x03000075, 0x241382a0, 0x74766352, 0x82178220, 0xfc042102, 0x02380482, 0x66796c67, 0x5689af12, 0x04070000, 0x80920000, 0x64616568,
9837  0xd36691d7, 0xcc201b82, 0x36210382, 0x27108268, 0xc3014208, 0x04010000, 0x243b0f82, 0x78746d68, 0x807e008a, 0x98010000, 0x06020000, 0x61636f6c,
9838  0xd8b0738c, 0x82050000, 0x0402291e, 0x7078616d, 0xda00ae01, 0x28201f82, 0x202c1082, 0x656d616e, 0x96bb5925, 0x84990000, 0x9e2c1382, 0x74736f70,
9839  0xef83aca6, 0x249b0000, 0xd22c3382, 0x70657270, 0x12010269, 0xf4040000, 0x08202f82, 0x012ecb84, 0x553c0000, 0x0f5fd5e9, 0x0300f53c, 0x00830008,
9840  0x7767b722, 0x002b3f82, 0xa692bd00, 0xfe0000d7, 0x83800380, 0x21f1826f, 0x00850002, 0x41820120, 0x40fec026, 0x80030000, 0x05821083, 0x07830120,
9841  0x0221038a, 0x24118200, 0x90000101, 0x82798200, 0x00022617, 0x00400008, 0x2009820a, 0x82098276, 0x82002006, 0x9001213b, 0x0223c883, 0x828a02bc,
9842  0x858f2010, 0xc5012507, 0x00023200, 0x04210083, 0x91058309, 0x6c412b03, 0x40007374, 0xac200000, 0x00830008, 0x01000523, 0x834d8380, 0x80032103,
9843  0x012101bf, 0x23b88280, 0x00800000, 0x0b830382, 0x07820120, 0x83800021, 0x88012001, 0x84002009, 0x2005870f, 0x870d8301, 0x2023901b, 0x83199501,
9844  0x82002015, 0x84802000, 0x84238267, 0x88002027, 0x8561882d, 0x21058211, 0x13880000, 0x01800022, 0x05850d85, 0x0f828020, 0x03208384, 0x03200582,
9845  0x47901b84, 0x1b850020, 0x1f821d82, 0x3f831d88, 0x3f410383, 0x84058405, 0x210982cd, 0x09830000, 0x03207789, 0xf38a1384, 0x01203782, 0x13872384,
9846  0x0b88c983, 0x0d898f84, 0x00202982, 0x23900383, 0x87008021, 0x83df8301, 0x86118d03, 0x863f880d, 0x8f35880f, 0x2160820f, 0x04830300, 0x1c220382,
9847  0x05820100, 0x4c000022, 0x09831182, 0x04001c24, 0x11823000, 0x0800082e, 0x00000200, 0xff007f00, 0xffffac20, 0x00220982, 0x09848100, 0xdf216682,
9848  0x843586d5, 0x06012116, 0x04400684, 0xa58120d7, 0x00b127d8, 0x01b88d01, 0x2d8685ff, 0xc100c621, 0xf4be0801, 0x9e011c01, 0x88021402, 0x1403fc02,
9849  0x9c035803, 0x1404de03, 0x50043204, 0xa2046204, 0x66051605, 0x1206bc05, 0xd6067406, 0x7e073807, 0x4e08ec07, 0x96086c08, 0x1009d008, 0x88094a09,
9850  0x800a160a, 0x560b040b, 0x2e0cc80b, 0xea0c820c, 0xa40d5e0d, 0x500eea0d, 0x280f960e, 0x1210b00f, 0xe0107410, 0xb6115211, 0x6e120412, 0x4c13c412,
9851  0xf613ac13, 0xae145814, 0x4015ea14, 0xa6158015, 0x1216b815, 0xc6167e16, 0x8e173417, 0x5618e017, 0xee18ba18, 0x96193619, 0x481ad419, 0xf01a9c1a,
9852  0xc81b5c1b, 0x4c1c041c, 0xea1c961c, 0x921d2a1d, 0x401ed21d, 0xe01e8e1e, 0x761f241f, 0xa61fa61f, 0x01821020, 0x8a202e34, 0xc820b220, 0x74211421,
9853  0xee219821, 0x86226222, 0x01820c23, 0x83238021, 0x23983c01, 0x24d823b0, 0x244a2400, 0x24902468, 0x250625ae, 0x25822560, 0x26f825f8, 0x82aa2658,
9854  0xd8be0801, 0x9a274027, 0x68280a28, 0x0e29a828, 0xb8292029, 0x362af829, 0x602a602a, 0x2a2b022b, 0xac2b5e2b, 0x202ce62b, 0x9a2c342c, 0x5c2d282d,
9855  0xaa2d782d, 0x262ee82d, 0x262fa62e, 0xf42fb62f, 0xc8305e30, 0xb4313e31, 0x9e321e32, 0x82331e33, 0x5c34ee33, 0x3a35ce34, 0xd4358635, 0x72362636,
9856  0x7637e636, 0x3a38d837, 0x1239a638, 0xae397439, 0x9a3a2e3a, 0x7c3b063b, 0x3a3ce83b, 0x223d963c, 0xec3d863d, 0xc63e563e, 0x9a3f2a3f, 0x6a401240,
9857  0x3641d040, 0x0842a241, 0x7a424042, 0xf042b842, 0xcc436243, 0x8a442a44, 0x5845ee44, 0xe245b645, 0xb4465446, 0x7a471447, 0x5448da47, 0x4049c648,
9858  0x15462400, 0x034d0808, 0x0b000700, 0x13000f00, 0x1b001700, 0x23001f00, 0x2b002700, 0x33002f00, 0x3b003700, 0x43003f00, 0x4b004700, 0x53004f00,
9859  0x5b005700, 0x63005f00, 0x6b006700, 0x73006f00, 0x7b007700, 0x83007f00, 0x8b008700, 0x00008f00, 0x15333511, 0x20039631, 0x20178205, 0xd3038221,
9860  0x20739707, 0x25008580, 0x028080fc, 0x05be8080, 0x04204a85, 0x05ce0685, 0x0107002a, 0x02000080, 0x00000400, 0x250d8b41, 0x33350100, 0x03920715,
9861  0x13820320, 0x858d0120, 0x0e8d0320, 0xff260d83, 0x00808000, 0x54820106, 0x04800223, 0x845b8c80, 0x41332059, 0x078b068f, 0x82000121, 0x82fe2039,
9862  0x84802003, 0x83042004, 0x23598a0e, 0x00180000, 0x03210082, 0x42ab9080, 0x73942137, 0x2013bb41, 0x8f978205, 0x2027a39b, 0x20b68801, 0x84b286fd,
9863  0x91c88407, 0x41032011, 0x11a51130, 0x15000027, 0x80ff8000, 0x11af4103, 0x841b0341, 0x8bd983fd, 0x9be99bc9, 0x8343831b, 0x21f1821f, 0xb58300ff,
9864  0x0f84e889, 0xf78a0484, 0x8000ff22, 0x0020eeb3, 0x14200082, 0x2130ef41, 0xeb431300, 0x4133200a, 0xd7410ecb, 0x9a07200b, 0x2027871b, 0x21238221,
9865  0xe7828080, 0xe784fd20, 0xe8848020, 0xfe808022, 0x08880d85, 0xba41fd20, 0x82248205, 0x85eab02a, 0x008022e7, 0x2cd74200, 0x44010021, 0xd34406eb,
9866  0x44312013, 0xcf8b0eef, 0x0d422f8b, 0x82332007, 0x0001212f, 0x8023cf82, 0x83000180, 0x820583de, 0x830682d4, 0x820020d4, 0x82dc850a, 0x20e282e9,
9867  0xb2ff85fe, 0x010327e9, 0x02000380, 0x0f440400, 0x0c634407, 0x68825982, 0x85048021, 0x260a825d, 0x010b0000, 0x4400ff00, 0x2746103f, 0x08d74209,
9868  0x4d440720, 0x0eaf4406, 0xc3441d20, 0x23078406, 0xff800002, 0x04845b83, 0x8d05b241, 0x1781436f, 0x6b8c87a5, 0x1521878e, 0x06474505, 0x01210783,
9869  0x84688c00, 0x8904828e, 0x441e8cf7, 0x0b270cff, 0x80008000, 0x45030003, 0xfb430fab, 0x080f4107, 0x410bf942, 0xd34307e5, 0x070d4207, 0x80800123,
9870  0x205d85fe, 0x849183fe, 0x20128404, 0x82809702, 0x00002217, 0x41839a09, 0x6b4408cf, 0x0733440f, 0x3b460720, 0x82798707, 0x97802052, 0x0000296f,
9871  0xff800004, 0x01800100, 0x0021ef89, 0x0a914625, 0x410a4d41, 0x00250ed4, 0x00050000, 0x056d4280, 0x210a7b46, 0x21481300, 0x46ed8512, 0x00210bd1,
9872  0x89718202, 0x21738877, 0x2b850001, 0x00220582, 0x87450a00, 0x0ddb4606, 0x41079b42, 0x9d420c09, 0x0b09420b, 0x8d820720, 0x9742fc84, 0x42098909,
9873  0x00241e0f, 0x00800014, 0x0b47da82, 0x0833442a, 0x49078d41, 0x2f450f13, 0x42278f17, 0x01200751, 0x22063742, 0x44808001, 0x20450519, 0x88068906,
9874  0x83fe2019, 0x4203202a, 0x1a941a58, 0x00820020, 0xe7a40e20, 0x420ce146, 0x854307e9, 0x0fcb4713, 0xff20a182, 0xfe209b82, 0x0c867f8b, 0x0021aea4,
9875  0x219fa40f, 0x7d41003b, 0x07194214, 0xbf440520, 0x071d4206, 0x6941a590, 0x80802309, 0x028900ff, 0xa9a4b685, 0xc5808021, 0x449b82ab, 0x152007eb,
9876  0x42134d46, 0x61440a15, 0x051e4208, 0x222b0442, 0x47001100, 0xfd412913, 0x17194714, 0x410f5b41, 0x02220773, 0x09428080, 0x21a98208, 0xd4420001,
9877  0x481c840d, 0x00232bc9, 0x42120000, 0xe74c261b, 0x149d4405, 0x07209d87, 0x410db944, 0x14421c81, 0x42fd2005, 0x80410bd2, 0x203d8531, 0x06874100,
9878  0x48256f4a, 0xcb420c95, 0x13934113, 0x44075d44, 0x044c0855, 0x00ff2105, 0xfe228185, 0x45448000, 0x22c5b508, 0x410c0000, 0x7b412087, 0x1bb74514,
9879  0x32429c85, 0x0a574805, 0x21208943, 0x8ba01300, 0x440dfb4e, 0x77431437, 0x245b4113, 0x200fb145, 0x41108ffe, 0x80203562, 0x00200082, 0x46362b42,
9880  0x1742178d, 0x4527830f, 0x0f830b2f, 0x4a138146, 0x802409a1, 0xfe8000ff, 0x94419982, 0x09294320, 0x04000022, 0x49050f4f, 0xcb470a63, 0x48032008,
9881  0x2b48067b, 0x85022008, 0x82638338, 0x00002209, 0x05af4806, 0x900e9f49, 0x84c5873f, 0x214285bd, 0x064900ff, 0x0c894607, 0x00000023, 0x4903820a,
9882  0x714319f3, 0x0749410c, 0x8a07a145, 0x02152507, 0xfe808000, 0x74490386, 0x8080211b, 0x0c276f82, 0x00018000, 0x48028003, 0x2b2315db, 0x43002f00,
9883  0x6f82142f, 0x44011521, 0x93510da7, 0x20e68508, 0x06494d80, 0x8e838020, 0x06821286, 0x124bff20, 0x25f3830c, 0x03800080, 0xe74a0380, 0x207b8715,
9884  0x876b861d, 0x4a152007, 0x07870775, 0xf6876086, 0x8417674a, 0x0a0021f2, 0x431c9743, 0x8d421485, 0x200b830b, 0x06474d03, 0x71828020, 0x04510120,
9885  0x42da8606, 0x1f831882, 0x001a0022, 0xff4d0082, 0x0b0f532c, 0x0d449b94, 0x4e312007, 0x074f12e7, 0x0bf3490b, 0xbb412120, 0x413f820a, 0xef490857,
9886  0x80002313, 0xe2830001, 0x6441fc20, 0x8b802006, 0x00012108, 0xfd201582, 0x492c9b48, 0x802014ff, 0x51084347, 0x0f4327f3, 0x17bf4a14, 0x201b7944,
9887  0x06964201, 0x134ffe20, 0x20d6830b, 0x25d78280, 0xfd800002, 0x05888000, 0x9318dc41, 0x21d282d4, 0xdb481800, 0x0dff542a, 0x45107743, 0xe14813f5,
9888  0x0f034113, 0x83135d45, 0x47b28437, 0xe4510e73, 0x21f58e06, 0x2b8400fd, 0x1041fcac, 0x08db4b0b, 0x421fdb41, 0xdf4b18df, 0x011d210a, 0x420af350,
9889  0x6e8308af, 0xac85cb86, 0x1e461082, 0x82b7a407, 0x411420a3, 0xa34130ab, 0x178f4124, 0x41139741, 0x86410d93, 0x82118511, 0x057243d8, 0x8941d9a4,
9890  0x3093480c, 0x4a13474f, 0xfb5016a9, 0x07ad4108, 0x4a0f9d42, 0xfe200fad, 0x4708aa41, 0x83482dba, 0x288f4d06, 0xb398c3bb, 0x44267b41, 0xb34439d7,
9891  0x0755410f, 0x200ebb45, 0x0f5f4215, 0x20191343, 0x06df5301, 0xf04c0220, 0x2ba64d07, 0x82050841, 0x430020ce, 0xa78f3627, 0x5213ff42, 0x2f970bc1,
9892  0x4305ab55, 0xa084111b, 0x450bac45, 0x5f4238b8, 0x010c2106, 0x0220ed82, 0x441bb344, 0x875010af, 0x0737480f, 0x490c5747, 0x0c840c03, 0x4c204b42,
9893  0x8ba905d7, 0x8b948793, 0x510c0c51, 0xfb4b24b9, 0x1b174107, 0x5709d74c, 0xd1410ca5, 0x079d480f, 0x201ff541, 0x06804780, 0x7d520120, 0x80002205,
9894  0x20a983fe, 0x47bb83fe, 0x1b8409b4, 0x81580220, 0x4e00202c, 0x4f41282f, 0x0eab4f17, 0x57471520, 0x0e0f4808, 0x8221e041, 0x3e1b4a8b, 0x4407175d,
9895  0x1b4b071f, 0x4a0f8b07, 0x174a0703, 0x0ba5411b, 0x430fb141, 0x0120057b, 0xfc20dd82, 0x4a056047, 0xf4850c0c, 0x01221982, 0x02828000, 0x1a5d088b,
9896  0x20094108, 0x8c0e3941, 0x4900200e, 0x7744434f, 0x200b870b, 0x0e4b5a33, 0x2b41f78b, 0x8b138307, 0x0b9f450b, 0x2406f741, 0xfd808001, 0x09475a00,
9897  0x84000121, 0x5980200e, 0x85450e5d, 0x832c8206, 0x4106831e, 0x00213814, 0x28b34810, 0x410c2f4b, 0x5f4a13d7, 0x0b2b4113, 0x6e43a883, 0x11174b05,
9898  0x4b066a45, 0xcc470541, 0x5000202b, 0xcb472f4b, 0x44b59f0f, 0xc5430b5b, 0x0d654907, 0x21065544, 0xd6828080, 0xfe201982, 0x8230ec4a, 0x120025c2,
9899  0x80ff8000, 0x4128d74d, 0x3320408b, 0x410a9f50, 0xdb822793, 0x822bd454, 0x61134b2e, 0x410b214a, 0xad4117c9, 0x0001211f, 0x4206854f, 0x4b430596,
9900  0x06bb5530, 0x2025cf46, 0x0ddd5747, 0x500ea349, 0x0f840fa7, 0x5213c153, 0x634e08d1, 0x0bbe4809, 0x59316e4d, 0x5b50053f, 0x203f6323, 0x5117eb46,
9901  0x94450a63, 0x246e410a, 0x63410020, 0x0bdb5f2f, 0x4233ab44, 0x39480757, 0x112d4a07, 0x7241118f, 0x000e2132, 0x9f286f41, 0x0f8762c3, 0x33350723,
9902  0x094e6415, 0x2010925f, 0x067252fe, 0xd0438020, 0x63a68225, 0x11203a4f, 0x480e6360, 0x5748131f, 0x079b521f, 0x200e2f43, 0x864b8315, 0x113348e7,
9903  0x85084e48, 0x06855008, 0x5880fd21, 0x7c420925, 0x0c414824, 0x37470c86, 0x1b8b422b, 0x5b0a8755, 0x23410c21, 0x0b83420b, 0x5a082047, 0xf482067f,
9904  0xa80b4c47, 0x0c0021cf, 0x20207b42, 0x0fb74100, 0x420b8744, 0xeb43076f, 0x0f6f420b, 0x4261fe20, 0x439aa00c, 0x215034e3, 0x0ff9570f, 0x4b1f2d5d,
9905  0x2d5d0c6f, 0x09634d0b, 0x1f51b8a0, 0x620f200c, 0xaf681e87, 0x24f94d07, 0x4e0f4945, 0xfe200c05, 0x22139742, 0x57048080, 0x23950c20, 0x97601585,
9906  0x4813201f, 0xad620523, 0x200f8f0f, 0x9e638f15, 0x00002181, 0x41342341, 0x0f930f0b, 0x210b4b62, 0x978f0001, 0xfe200f84, 0x8425c863, 0x2704822b,
9907  0x80000a00, 0x00038001, 0x610e9768, 0x834514bb, 0x0bc3430f, 0x2107e357, 0x80848080, 0x4400fe21, 0x2e410983, 0x00002a1a, 0x00000700, 0x800380ff,
9908  0x0fdf5800, 0x59150021, 0xd142163d, 0x0c02410c, 0x01020025, 0x65800300, 0x00240853, 0x1d333501, 0x15220382, 0x35420001, 0x44002008, 0x376406d7,
9909  0x096f6b19, 0x480bc142, 0x8f4908a7, 0x211f8b1f, 0x9e830001, 0x0584fe20, 0x4180fd21, 0x11850910, 0x8d198259, 0x000021d4, 0x5a08275d, 0x275d1983,
9910  0x06d9420e, 0x9f08b36a, 0x0f7d47b5, 0x8d8a2f8b, 0x4c0e0b57, 0xe7410e17, 0x42d18c1a, 0xb351087a, 0x1ac36505, 0x4b4a2f20, 0x0b9f450d, 0x430beb53,
9911  0xa7881015, 0xa5826a83, 0x80200f82, 0x86185a65, 0x4100208e, 0x176c3367, 0x0fe7650b, 0x4a17ad4b, 0x0f4217ed, 0x112e4206, 0x41113a42, 0xf7423169,
9912  0x0cb34737, 0x560f8b46, 0xa75407e5, 0x5f01200f, 0x31590c48, 0x80802106, 0x42268841, 0x0020091e, 0x4207ef64, 0x69461df7, 0x138d4114, 0x820f5145,
9913  0x53802090, 0xff200529, 0xb944b183, 0x417e8505, 0x00202561, 0x15210082, 0x42378200, 0x9b431cc3, 0x004f220d, 0x0dd54253, 0x4213f149, 0x7d41133b,
9914  0x42c9870b, 0x802010f9, 0x420b2c42, 0x8f441138, 0x267c4408, 0x600cb743, 0x8f4109d3, 0x05ab701d, 0x83440020, 0x3521223f, 0x0b794733, 0xfb62fe20,
9915  0x4afd2010, 0xaf410ae7, 0x25ce8525, 0x01080000, 0x7b6b0000, 0x0973710b, 0x82010021, 0x49038375, 0x33420767, 0x052c4212, 0x58464b85, 0x41fe2005,
9916  0x50440c27, 0x000c2209, 0x1cb36b80, 0x9b06df44, 0x0f93566f, 0x52830220, 0xfe216e8d, 0x200f8200, 0x0fb86704, 0xb057238d, 0x050b5305, 0x7217eb47,
9917  0xbd410b6b, 0x0f214610, 0x871f9956, 0x1e91567e, 0x2029b741, 0x20008200, 0x18b7410a, 0x27002322, 0x41095543, 0x0f8f0fb3, 0x41000121, 0x889d111c,
9918  0x14207b82, 0x00200382, 0x73188761, 0x475013a7, 0x6e33200c, 0x234e0ea3, 0x9b138313, 0x08e54d17, 0x9711094e, 0x2ee74311, 0x4908875e, 0xd75d1f1f,
9919  0x19ab5238, 0xa2084d48, 0x63a7a9b3, 0x55450b83, 0x0fd74213, 0x440d814c, 0x4f481673, 0x05714323, 0x13000022, 0x412e1f46, 0xdf493459, 0x21c7550f,
9920  0x8408215f, 0x201d49cb, 0xb1103043, 0x0f0d65d7, 0x452b8d41, 0x594b0f8d, 0x0b004605, 0xb215eb46, 0x000a24d7, 0x47000080, 0x002118cf, 0x06436413,
9921  0x420bd750, 0x2b500743, 0x076a470c, 0x4105c050, 0xd942053f, 0x0d00211a, 0x5f44779c, 0x0ce94805, 0x51558186, 0x14a54c0b, 0x49082b41, 0x0a4b0888,
9922  0x8080261f, 0x0d000000, 0x20048201, 0x1deb6a03, 0x420cb372, 0x07201783, 0x4306854d, 0x8b830c59, 0x59093c74, 0x0020250f, 0x67070f4a, 0x2341160b,
9923  0x00372105, 0x431c515d, 0x554e17ef, 0x0e5d6b05, 0x41115442, 0xb74a1ac1, 0x2243420a, 0x5b4f878f, 0x7507200f, 0x384b086f, 0x09d45409, 0x0020869a,
9924  0x12200082, 0xab460382, 0x10075329, 0x54138346, 0xaf540fbf, 0x1ea75413, 0x9a0c9e54, 0x0f6b44c1, 0x41000021, 0x47412a4f, 0x07374907, 0x5310bf76,
9925  0xff2009b4, 0x9a09a64c, 0x8200208d, 0x34c34500, 0x970fe141, 0x1fd74b0f, 0x440a3850, 0x206411f0, 0x27934609, 0x470c5d41, 0x555c2947, 0x1787540f,
9926  0x6e0f234e, 0x7d540a1b, 0x1d736b08, 0x0026a088, 0x80000e00, 0x9b5200ff, 0x08ef4318, 0x450bff77, 0x1d4d0b83, 0x081f7006, 0xcb691b86, 0x4b022008,
9927  0xc34b0b33, 0x1d0d4a0c, 0x8025a188, 0x0b000000, 0x52a38201, 0xbf7d0873, 0x0c234511, 0x8f0f894a, 0x4101200f, 0x0c880c9d, 0x2b418ea1, 0x06c74128,
9928  0x66181341, 0x7b4c0bb9, 0x0c06630b, 0xfe200c87, 0x9ba10882, 0x27091765, 0x01000008, 0x02800380, 0x48113f4e, 0x29430cf5, 0x09a75a0b, 0x31618020,
9929  0x6d802009, 0x61840e33, 0x8208bf51, 0x0c637d61, 0x7f092379, 0x4f470f4b, 0x1797510c, 0x46076157, 0xf5500fdf, 0x0f616910, 0x1171fe20, 0x82802006,
9930  0x08696908, 0x41127a4c, 0x3f4a15f3, 0x01042607, 0x0200ff00, 0x1cf77700, 0xff204185, 0x00235b8d, 0x43100000, 0x3b22243f, 0x3b4d3f00, 0x0b937709,
9931  0xad42f18f, 0x0b1f420f, 0x51084b43, 0x8020104a, 0xb557ff83, 0x052b7f2a, 0x0280ff22, 0x250beb78, 0x00170013, 0xbf6d2500, 0x07db760e, 0x410e2b7f,
9932  0x00230e4f, 0x49030000, 0x0582055b, 0x07000326, 0x00000b00, 0x580bcd46, 0x00200cdd, 0x57078749, 0x8749160f, 0x0f994f0a, 0x41134761, 0x01200b31,
9933  0xeb796883, 0x0b41500b, 0x0e90b38e, 0x202e7b51, 0x05d95801, 0x41080570, 0x1d530fc9, 0x0b937a0f, 0xaf8eb387, 0xf743b98f, 0x07c74227, 0x80000523,
9934  0x0fcb4503, 0x430ca37b, 0x7782077f, 0x8d0a9947, 0x08af4666, 0xeb798020, 0x6459881e, 0xc3740bbf, 0x0feb6f0b, 0x20072748, 0x052b6102, 0x435e0584,
9935  0x7d088308, 0x03200afd, 0x92109e41, 0x28aa8210, 0x80001500, 0x80030000, 0x0fdb5805, 0x209f4018, 0xa7418d87, 0x0aa3440f, 0x20314961, 0x073a52ff,
9936  0x6108505d, 0x43181051, 0x00223457, 0xe7820500, 0x50028021, 0x81410d33, 0x063d7108, 0xdb41af84, 0x4d888205, 0x00201198, 0x463d835f, 0x152106d7,
9937  0x0a355a33, 0x6917614e, 0x75411f4d, 0x184b8b07, 0x1809c344, 0x21091640, 0x0b828000, 0x42808021, 0x26790519, 0x86058605, 0x2428422d, 0x22123b42,
9938  0x42000080, 0xf587513b, 0x7813677b, 0xaf4d139f, 0x00ff210c, 0x5e0a1d57, 0x3b421546, 0x01032736, 0x02000380, 0x41180480, 0x2f420f07, 0x0c624807,
9939  0x00000025, 0x18000103, 0x83153741, 0x430120c3, 0x042106b2, 0x088d4d00, 0x2f830620, 0x1810434a, 0x18140345, 0x8507fb41, 0x5ee582ea, 0x0023116c,
9940  0x8d000600, 0x053b56af, 0xa6554fa2, 0x0d704608, 0x40180d20, 0x47181a43, 0xd37b07ff, 0x0b79500c, 0x420fd745, 0x47450bd9, 0x8471830a, 0x095a777e,
9941  0x84137542, 0x82002013, 0x2f401800, 0x0007213b, 0x4405e349, 0x0d550ff3, 0x16254c0c, 0x820ffe4a, 0x0400218a, 0x89066f41, 0x106b414f, 0xc84d0120,
9942  0x80802206, 0x0c9a4b03, 0x00100025, 0x68000200, 0x9d8c2473, 0x44134344, 0xf36a0f33, 0x4678860f, 0x1b440a25, 0x41988c0a, 0x80201879, 0x43079b5e,
9943  0x4a18080b, 0x0341190b, 0x1259530c, 0x43251552, 0x908205c8, 0x0cac4018, 0x86000421, 0x0e504aa2, 0x0020b891, 0xfb450082, 0x51132014, 0x8f5205f3,
9944  0x35052108, 0x8505cb59, 0x0f6d4f70, 0x82150021, 0x29af5047, 0x4f004b24, 0x75795300, 0x1b595709, 0x460b6742, 0xbf4b0f0d, 0x5743870b, 0xcb6d1461,
9945  0x08f64505, 0x4e05ab6c, 0x334126c3, 0x0bcb6b0d, 0x1811034d, 0x4111ef4b, 0x814f1ce5, 0x20af8227, 0x07fd7b80, 0x41188e84, 0xef410f33, 0x80802429,
9946  0x410d0000, 0xa34205ab, 0x76b7881c, 0xff500b89, 0x0741430f, 0x20086f4a, 0x209d8200, 0x234c18fd, 0x05d4670a, 0x4509af51, 0x9642078d, 0x189e831d,
9947  0x7c1cc74b, 0xcd4c07b9, 0x0e7c440f, 0x8b7b0320, 0x21108210, 0xc76c8080, 0x03002106, 0x6b23bf41, 0xc549060b, 0x7946180b, 0x0ff7530f, 0x17ad4618,
9948  0x200ecd45, 0x208c83fd, 0x5e0488fe, 0x032009c6, 0x420d044e, 0x0d8f0d7f, 0x00820020, 0x18001021, 0x6d273b45, 0xfd4c0c93, 0xcf451813, 0x0fe5450f,
9949  0x5a47c382, 0x820a8b0a, 0x282b4998, 0x410a8b5b, 0x4b232583, 0x54004f00, 0x978f0ce3, 0x500f1944, 0xa95f1709, 0x0280220b, 0x05ba7080, 0xa1530682,
9950  0x06324c13, 0x91412582, 0x05536e2c, 0x63431020, 0x0f434706, 0x8c11374c, 0x176143d7, 0x4d0f454c, 0xd3680bed, 0x0bee4d17, 0x212b9a41, 0x0f530a00,
9951  0x140d531c, 0x43139143, 0x95610e8d, 0x0f094415, 0x4205fb56, 0x1b4205cf, 0x17015225, 0x5e0c477f, 0xaf6e0aeb, 0x0ff36218, 0x04849a84, 0x0a454218,
9952  0x9c430420, 0x23c6822b, 0x04000102, 0x45091b4b, 0xf05f0955, 0x82802007, 0x421c2023, 0x5218282b, 0x7b53173f, 0x0fe7480c, 0x74173b7f, 0x47751317,
9953  0x634d1807, 0x0f6f430f, 0x24086547, 0xfc808002, 0x0b3c7f80, 0x10840120, 0x188d1282, 0x20096b43, 0x0fc24403, 0x00260faf, 0x0180000b, 0x3f500280,
9954  0x18002019, 0x450b4941, 0xf3530fb9, 0x18002010, 0x8208a551, 0x06234d56, 0xcb58a39b, 0xc3421805, 0x1313461e, 0x0f855018, 0xd34b0120, 0x6cfe2008,
9955  0x574f0885, 0x09204114, 0x07000029, 0x00008000, 0x44028002, 0x01420f57, 0x10c95c10, 0x11184c18, 0x80221185, 0x7f421e00, 0x00732240, 0x09cd4977,
9956  0x6d0b2b42, 0x4f180f8f, 0x8f5a0bcb, 0x9b0f830f, 0x0fb9411f, 0x230b5756, 0x00fd8080, 0x82060745, 0x000121d5, 0x8e0fb277, 0x4a8d4211, 0x24061c53,
9957  0x04000007, 0x12275280, 0x430c954c, 0x80201545, 0x200f764f, 0x20008200, 0x20ce8308, 0x09534f02, 0x660edf64, 0x73731771, 0xe7411807, 0x20a2820c,
9958  0x13b64404, 0x8f5d6682, 0x1d6b4508, 0x0cff4d18, 0x3348c58f, 0x0fc34c07, 0x31558b84, 0x8398820f, 0x17514712, 0x240b0e46, 0x80000a00, 0x093b4502,
9959  0x420f9759, 0xa54c0bf1, 0x0f2b470c, 0x410d314b, 0x2584170c, 0x73b30020, 0xb55fe782, 0x204d8410, 0x08e043fe, 0x4f147e41, 0x022008ab, 0x4b055159,
9960  0x2950068f, 0x00022208, 0x48511880, 0x82002009, 0x00112300, 0x634dff00, 0x24415f27, 0x180f6d43, 0x4d0b5d45, 0x4d5f05ef, 0x01802317, 0x56188000,
9961  0xa7840807, 0xc6450220, 0x21ca8229, 0x4b781a00, 0x3359182c, 0x0cf3470f, 0x180bef46, 0x420b0354, 0xff470b07, 0x4515200a, 0x9758239b, 0x4a80200c,
9962  0xd2410a26, 0x05fb4a08, 0x4b05e241, 0x03200dc9, 0x92290941, 0x00002829, 0x00010900, 0x5b020001, 0x23201363, 0x460d776a, 0xef530fdb, 0x209a890c,
9963  0x13fc4302, 0x00008024, 0xc4820104, 0x08820220, 0x20086b5b, 0x18518700, 0x8408d349, 0x0da449a1, 0x00080024, 0x7b690280, 0x4c438b1a, 0x01220f63,
9964  0x4c878000, 0x5c149c53, 0xfb430868, 0x2f56181e, 0x0ccf7b1b, 0x0f075618, 0x2008e347, 0x14144104, 0x00207f83, 0x00207b82, 0x201adf47, 0x16c35a13,
9965  0x540fdf47, 0x802006c8, 0x5418f185, 0x29430995, 0x00002419, 0x58001600, 0x5720316f, 0x4d051542, 0x4b7b1b03, 0x138f4707, 0xb747b787, 0x4aab8213,
9966  0x058305fc, 0x20115759, 0x82128401, 0x0a0b44e8, 0x46800121, 0xe64210d0, 0x82129312, 0x4bffdffe, 0x3b41171b, 0x9b27870f, 0x808022ff, 0x085c68fe,
9967  0x41800021, 0x01410b20, 0x001a213a, 0x47480082, 0x11374e12, 0x56130b4c, 0xdf4b0c65, 0x0b0f590b, 0x0f574c18, 0x830feb4b, 0x075f480f, 0x480b4755,
9968  0x40490b73, 0x80012206, 0x09d74280, 0x80fe8022, 0x80210e86, 0x056643ff, 0x10820020, 0x420b2646, 0x0b58391a, 0xd74c1808, 0x078b4e22, 0x2007f55f,
9969  0x4b491807, 0x83802017, 0x65aa82a7, 0x3152099e, 0x068b7616, 0x9b431220, 0x09bb742c, 0x500e376c, 0x8342179b, 0x0a4d5d0f, 0x8020a883, 0x180cd349,
9970  0x2016bb4b, 0x14476004, 0x84136c43, 0x08cf7813, 0x4f4c0520, 0x156f420f, 0x20085f42, 0x6fd3be03, 0xd4d30803, 0xa7411420, 0x004b222c, 0x0d3b614f,
9971  0x3f702120, 0x1393410a, 0x8f132745, 0x47421827, 0x41e08209, 0xb05e2bb9, 0x18b7410c, 0x18082647, 0x4107a748, 0xeb8826bf, 0x0ca76018, 0x733ecb41,
9972  0xd0410d83, 0x43ebaf2a, 0x0420067f, 0x721dab4c, 0x472005bb, 0x4105d341, 0x334844cb, 0x20dba408, 0x47d6ac00, 0x034e3aef, 0x0f8f421b, 0x930f134d,
9973  0x3521231f, 0xb7421533, 0x42f5ad0a, 0x1e961eaa, 0x17000022, 0x4c367b50, 0x7d491001, 0x0bf5520f, 0x4c18fda7, 0xb8460c55, 0x83fe2005, 0x00fe25b9,
9974  0x80000180, 0x9e751085, 0x261b5c12, 0x82110341, 0x001123fb, 0x4518fe80, 0xf38c2753, 0x6d134979, 0x295107a7, 0xaf5f180f, 0x0fe3660c, 0x180b6079,
9975  0x2007bd5f, 0x9aab9103, 0x2f4d1811, 0x05002109, 0x44254746, 0x1d200787, 0x450bab75, 0x4f180f57, 0x4f181361, 0x3b831795, 0xeb4b0120, 0x0b734805,
9976  0x84078f48, 0x2e1b47bc, 0x00203383, 0xaf065f45, 0x831520d7, 0x130f51a7, 0x1797bf97, 0x2b47d783, 0x18fe2005, 0x4a18a44f, 0xa64d086d, 0x1ab0410d,
9977  0x6205a258, 0xdbab069f, 0x4f06f778, 0xa963081d, 0x133b670a, 0x8323d141, 0x13195b23, 0x530f5e70, 0xe5ad0824, 0x58001421, 0x1f472b4b, 0x47bf410c,
9978  0x82000121, 0x83fe20cb, 0x07424404, 0x68068243, 0xd7ad0d3d, 0x00010d26, 0x80020000, 0x4a1c6f43, 0x23681081, 0x10a14f13, 0x8a070e57, 0x430a848f,
9979  0x7372243e, 0x4397a205, 0xb56c1021, 0x43978f0f, 0x64180505, 0x99aa0ff2, 0x0e000022, 0x20223341, 0x094b4f37, 0x074a3320, 0x2639410a, 0xfe208e84,
9980  0x8b0e0048, 0x508020a3, 0x9e4308fe, 0x073f4115, 0xe3480420, 0x0c9b5f1b, 0x7c137743, 0x9a95185b, 0x6122b148, 0x979b08df, 0x0fe36c18, 0x48109358,
9981  0x23441375, 0x0ffd5c0b, 0x180fc746, 0x2011d157, 0x07e95702, 0x58180120, 0x18770ac3, 0x51032008, 0x7d4118e3, 0x80802315, 0x3b4c1900, 0xbb5a1830,
9982  0x0ceb6109, 0x5b0b3d42, 0x4f181369, 0x4f180b8d, 0x4f180f75, 0x355a1b81, 0x200d820d, 0x18e483fd, 0x4528854f, 0x89420846, 0x1321411f, 0x44086b60,
9983  0x07421d77, 0x107d4405, 0x4113fd41, 0x5a181bf1, 0x4f180db3, 0x8021128f, 0x20f68280, 0x44a882fe, 0x334d249a, 0x052f6109, 0x1520c3a7, 0xef4eb783,
9984  0x4ec39b1b, 0xc4c90ee7, 0x20060b4d, 0x256f4905, 0x4d0cf761, 0xcf9b1f13, 0xa213d74e, 0x0e1145d4, 0x50135b42, 0xcb4e398f, 0x20d79f27, 0x08865d80,
9985  0x186d5018, 0xa90f7142, 0x067342d7, 0x3f450420, 0x65002021, 0xe3560771, 0x24d38f23, 0x15333531, 0x0eb94d01, 0x451c9f41, 0x384322fb, 0x00092108,
9986  0x19af6b18, 0x6e0c6f5a, 0xbd770bfb, 0x22bb7718, 0x20090f57, 0x25e74204, 0x4207275a, 0xdb5408ef, 0x1769450f, 0x1b1b5518, 0x210b1f57, 0x5e4c8001,
9987  0x55012006, 0x802107f1, 0x0a306a80, 0x45808021, 0x0d850b88, 0x31744f18, 0x1808ec54, 0x2009575b, 0x45ffa505, 0x1b420c73, 0x180f9f0f, 0x4a0cf748,
9988  0x501805b2, 0x00210f40, 0x4d118f80, 0xd6823359, 0x072b5118, 0x314ad7aa, 0x8fc79f08, 0x45d78b1f, 0xfe20058f, 0x23325118, 0x7b54d9b5, 0x9fc38f46,
9989  0x10bb410f, 0x41077b42, 0xc1410faf, 0x27cf441d, 0x46051b4f, 0x04200683, 0x2121d344, 0x8f530043, 0x8fcf9f0e, 0x21df8c1f, 0x50188000, 0x5d180e52,
9990  0xfd201710, 0x4405c341, 0xd68528e3, 0x20071f6b, 0x1b734305, 0x6b080957, 0x7d422b1f, 0x67002006, 0x7f8317b1, 0x2024cb48, 0x08676e00, 0x8749a39b,
9991  0x18132006, 0x410a6370, 0x8f490b47, 0x7e1f8f13, 0x551805c3, 0x4c180915, 0xfe200e2f, 0x244d5d18, 0x270bcf44, 0xff000019, 0x04800380, 0x5f253342,
9992  0xff520df7, 0x13274c18, 0x5542dd93, 0x0776181b, 0xf94a1808, 0x084a4c0c, 0x4308ea5b, 0xde831150, 0x7900fd21, 0x00492c1e, 0x060f4510, 0x17410020,
9993  0x0ce74526, 0x6206b341, 0x1f561083, 0x9d6c181b, 0x08a0500e, 0x112e4118, 0x60000421, 0xbf901202, 0x4408e241, 0xc7ab0513, 0xb40f0950, 0x055943c7,
9994  0x4f18ff20, 0xc9ae1cad, 0x32b34f18, 0x7a180120, 0x3d520a05, 0x53d1b40a, 0x80200813, 0x1b815018, 0x832bf86f, 0x67731847, 0x297f4308, 0x6418d54e,
9995  0x734213f7, 0x056b4b27, 0xdba5fe20, 0x1828aa4e, 0x2031a370, 0x06cb6101, 0x2040ad41, 0x07365300, 0x2558d985, 0x83fe200c, 0x0380211c, 0x542c4743,
9996  0x052006b7, 0x6021df45, 0x897b0707, 0x18d3c010, 0x20090e70, 0x1d5843ff, 0x540a0e44, 0x002126c5, 0x322f7416, 0x636a5720, 0x0f317409, 0x610fe159,
9997  0x294617e7, 0x08555213, 0x2006a75d, 0x6cec84fd, 0xfb5907be, 0x3a317405, 0x83808021, 0x180f20ea, 0x4626434a, 0x531818e3, 0xdb59172d, 0x0cbb460c,
9998  0x2013d859, 0x18b94502, 0x8f46188d, 0x77521842, 0x0a184e38, 0x9585fd20, 0x6a180684, 0xc64507e9, 0x51cbb230, 0xd3440cf3, 0x17ff6a0f, 0x450f5b42,
9999  0x276407c1, 0x4853180a, 0x21ccb010, 0xcf580013, 0x0c15442d, 0x410a1144, 0x1144359d, 0x5cfe2006, 0xa1410a43, 0x2bb64519, 0x2f5b7618, 0xb512b745,
10000  0x0cfd6fd1, 0x42089f59, 0xb8450c70, 0x0000232d, 0x50180900, 0xb9491ae3, 0x0fc37610, 0x01210f83, 0x0f3b4100, 0xa01b2742, 0x0ccd426f, 0x6e8f6f94,
10001  0x9c808021, 0xc7511870, 0x17c74b08, 0x9b147542, 0x44fe2079, 0xd5480c7e, 0x95ef861d, 0x101b597b, 0xf5417594, 0x9f471808, 0x86868d0e, 0x3733491c,
10002  0x690f4d6d, 0x43440b83, 0x1ba94c0b, 0x660cd16b, 0x802008ae, 0x74126448, 0xcb4f38a3, 0x2cb74b0b, 0x47137755, 0xe3971777, 0x1b5d0120, 0x057a4108,
10003  0x6e08664d, 0x17421478, 0x11af4208, 0x850c3f42, 0x08234f0c, 0x4321eb4a, 0xf3451095, 0x0f394e0f, 0x4310eb45, 0xc09707b1, 0x54431782, 0xaec08d1d,
10004  0x0f434dbb, 0x9f0c0b45, 0x0a3b4dbb, 0x4618bdc7, 0x536032eb, 0x17354213, 0x4d134169, 0xc7a30c2f, 0x4e254342, 0x174332cf, 0x43cdae17, 0x6b4706e4,
10005  0x0e16430d, 0x530b5542, 0x2f7c26bb, 0x13075f31, 0x43175342, 0x60181317, 0x6550114e, 0x28624710, 0x58070021, 0x59181683, 0x2d540cf5, 0x05d5660c,
10006  0x20090c7b, 0x0e157e02, 0x8000ff2b, 0x14000080, 0x80ff8000, 0x27137e03, 0x336a4b20, 0x0f817107, 0x13876e18, 0x730f2f7e, 0x2f450b75, 0x6d02200b,
10007  0x6d66094c, 0x4b802009, 0x15820a02, 0x2f45fe20, 0x5e032006, 0x00202fd9, 0x450af741, 0xeb412e0f, 0x0ff3411f, 0x420a8b65, 0xf7410eae, 0x1c664810,
10008  0x540e1145, 0xbfa509f3, 0x42302f58, 0x80200c35, 0xcb066c47, 0x4b1120c1, 0x41492abb, 0x34854110, 0xa7097b72, 0x251545c7, 0x4b2c7f56, 0xc5b40bab,
10009  0x940cd54e, 0x2e6151c8, 0x09f35f18, 0x4b420420, 0x09677121, 0x8f24f357, 0x1b5418e1, 0x08915a1f, 0x3143d894, 0x22541805, 0x1b9b4b0e, 0x8c0d3443,
10010  0x1400240d, 0x18ff8000, 0x582e6387, 0xf99b2b3b, 0x8807a550, 0x17a14790, 0x2184fd20, 0x5758fe20, 0x2354882c, 0x15000080, 0x5e056751, 0x334c2c2f,
10011  0x97c58f0c, 0x1fd7410f, 0x0d4d4018, 0x4114dc41, 0x04470ed6, 0x0dd54128, 0x00820020, 0x02011523, 0x22008700, 0x86480024, 0x0001240a, 0x8682001a,
10012  0x0002240b, 0x866c000e, 0x8a03200b, 0x8a042017, 0x0005220b, 0x22218614, 0x84060000, 0x86012017, 0x8212200f, 0x250b8519, 0x000d0001, 0x0b850031,
10013  0x07000224, 0x0b862600, 0x11000324, 0x0b862d00, 0x238a0420, 0x0a000524, 0x17863e00, 0x17840620, 0x01000324, 0x57820904, 0x0b85a783, 0x0b85a785,
10014  0x0b85a785, 0x22000325, 0x85007a00, 0x85a7850b, 0x85a7850b, 0x22a7850b, 0x82300032, 0x00342201, 0x0805862f, 0x35003131, 0x54207962, 0x74736972,
10015  0x47206e61, 0x6d6d6972, 0x65527265, 0x616c7567, 0x58545472, 0x6f725020, 0x43796767, 0x6e61656c, 0x30325454, 0x822f3430, 0x35313502, 0x79006200,
10016  0x54002000, 0x69007200, 0x74007300, 0x6e006100, 0x47200f82, 0x6d240f84, 0x65006d00, 0x52200982, 0x67240582, 0x6c007500, 0x72201d82, 0x54222b82,
10017  0x23825800, 0x19825020, 0x67006f22, 0x79220182, 0x1b824300, 0x3b846520, 0x1f825420, 0x41000021, 0x1422099b, 0x0b410000, 0x87088206, 0x01012102,
10018  0x78080982, 0x01020101, 0x01040103, 0x01060105, 0x01080107, 0x010a0109, 0x010c010b, 0x010e010d, 0x0110010f, 0x01120111, 0x01140113, 0x01160115,
10019  0x01180117, 0x011a0119, 0x011c011b, 0x011e011d, 0x0020011f, 0x00040003, 0x00060005, 0x00080007, 0x000a0009, 0x000c000b, 0x000e000d, 0x0010000f,
10020  0x00120011, 0x00140013, 0x00160015, 0x00180017, 0x001a0019, 0x001c001b, 0x001e001d, 0x08bb821f, 0x22002142, 0x24002300, 0x26002500, 0x28002700,
10021  0x2a002900, 0x2c002b00, 0x2e002d00, 0x30002f00, 0x32003100, 0x34003300, 0x36003500, 0x38003700, 0x3a003900, 0x3c003b00, 0x3e003d00, 0x40003f00,
10022  0x42004100, 0x4b09f382, 0x00450044, 0x00470046, 0x00490048, 0x004b004a, 0x004d004c, 0x004f004e, 0x00510050, 0x00530052, 0x00550054, 0x00570056,
10023  0x00590058, 0x005b005a, 0x005d005c, 0x005f005e, 0x01610060, 0x01220121, 0x01240123, 0x01260125, 0x01280127, 0x012a0129, 0x012c012b, 0x012e012d,
10024  0x0130012f, 0x01320131, 0x01340133, 0x01360135, 0x01380137, 0x013a0139, 0x013c013b, 0x013e013d, 0x0140013f, 0x00ac0041, 0x008400a3, 0x00bd0085,
10025  0x00e80096, 0x008e0086, 0x009d008b, 0x00a400a9, 0x008a00ef, 0x008300da, 0x00f20093, 0x008d00f3, 0x00880097, 0x00de00c3, 0x009e00f1, 0x00f500aa,
10026  0x00f600f4, 0x00ad00a2, 0x00c700c9, 0x006200ae, 0x00900063, 0x00cb0064, 0x00c80065, 0x00cf00ca, 0x00cd00cc, 0x00e900ce, 0x00d30066, 0x00d100d0,
10027  0x006700af, 0x009100f0, 0x00d400d6, 0x006800d5, 0x00ed00eb, 0x006a0089, 0x006b0069, 0x006c006d, 0x00a0006e, 0x0071006f, 0x00720070, 0x00750073,
10028  0x00760074, 0x00ea0077, 0x007a0078, 0x007b0079, 0x007c007d, 0x00a100b8, 0x007e007f, 0x00810080, 0x00ee00ec, 0x6e750eba, 0x646f6369, 0x78302365,
10029  0x31303030, 0x32200e8d, 0x33200e8d, 0x34200e8d, 0x35200e8d, 0x36200e8d, 0x37200e8d, 0x38200e8d, 0x39200e8d, 0x61200e8d, 0x62200e8d, 0x63200e8d,
10030  0x64200e8d, 0x65200e8d, 0x66200e8d, 0x31210e8c, 0x8d0e8d30, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef,
10031  0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x8d3120ef, 0x66312def, 0x6c656406, 0x04657465, 0x6f727545, 0x3820ec8c, 0x3820ec8d,
10032  0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d, 0x3820ec8d,
10033  0x3820ec8d, 0x200ddc41, 0x0ddc4139, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920,
10034  0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0xef8d3920, 0x00663923, 0x48fa0500, 0x00f762f9,
10035 };
10036 
10037 static void GetDefaultCompressedFontDataTTF(const void** ttf_compressed_data, unsigned int* ttf_compressed_size)
10038 {
10039  *ttf_compressed_data = proggy_clean_ttf_compressed_data;
10040  *ttf_compressed_size = proggy_clean_ttf_compressed_size;
10041 }
10042 
10043 //-----------------------------------------------------------------------------
10044 
10045 //---- Include imgui_user.inl at the end of imgui.cpp
10046 //---- So you can include code that extends ImGui using its private data/functions.
10047 #ifdef IMGUI_INCLUDE_IMGUI_USER_INL
10048 #include "imgui_user.inl"
10049 #endif
10050 
10051 //-----------------------------------------------------------------------------
#define stb__in2(x)
Definition: imgui.cpp:9746
#define IM_INT_MAX
Definition: imgui.cpp:607
static bool InputTextFilterCharacter(unsigned int *p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void *user_data)
Definition: imgui.cpp:5529
IMGUI_API void PlotHistogram(const char *label, const float *values, int values_count, int values_offset=0, const char *overlay_text=NULL, float scale_min=FLT_MAX, float scale_max=FLT_MAX, ImVec2 graph_size=ImVec2(0, 0), size_t stride=sizeof(float))
Definition: imgui.cpp:5117
static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_WHITE(14, 3)
static bool ItemAdd(const ImGuiAabb &bb, const ImGuiID *id)
Definition: imgui.cpp:6528
IMGUI_API void SetNextWindowFocus()
Definition: imgui.cpp:3627
static void RenderTextClipped(ImVec2 pos, const char *text, const char *text_end, const ImVec2 *text_size_if_known, const ImVec2 &clip_max)
Definition: imgui.cpp:2255
IMGUI_API bool RadioButton(const char *label, bool active)
Definition: imgui.cpp:5186
IMGUI_API void SetWindowFocus()
Definition: imgui.cpp:3593
static int ChildWindowComparer(const void *lhs, const void *rhs)
Definition: imgui.cpp:1961
unsigned int ImU32
Definition: imgui.h:34
IMGUI_API void PopItemWidth()
Definition: imgui.cpp:3256
static float CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x)
Definition: imgui.cpp:2188
unsigned short y0
Definition: stb_truetype.h:499
IMGUI_API void GetTexDataAsAlpha8(unsigned char **out_pixels, int *out_width, int *out_height, int *out_bytes_per_pixel=NULL)
Definition: imgui.cpp:7278
IMGUI_API ImVec2 GetWindowSize()
Definition: imgui.cpp:3523
static const char * GetClipboardTextFn_DefaultImpl()
Definition: imgui.cpp:8342
IMGUI_API void BeginTooltip()
Definition: imgui.cpp:2564
IMGUI_API int GetInt(ImGuiID key, int default_val=0) const
Definition: imgui.cpp:1245
#define STB_TEXTEDIT_STRING
Definition: imgui.cpp:395
signed short XAdvance
Definition: imgui.h:937
IMGUI_API bool Checkbox(const char *label, bool *v)
Definition: imgui.cpp:5128
static ImVector< ImGuiStorage::Pair >::iterator LowerBound(ImVector< ImGuiStorage::Pair > &data, ImU32 key)
Definition: imgui.cpp:1223
static float ImSaturate(float f)
Definition: imgui.cpp:639
IMGUI_API void Clear()
Definition: imgui.cpp:7603
IMGUI_API void TextWrappedV(const char *fmt, va_list args)
Definition: imgui.cpp:3825
ImVec2 DisplayOffset
Definition: imgui.h:930
IMGUI_API bool CollapsingHeader(const char *label, const char *str_id=NULL, bool display_frame=true, bool default_open=false)
Definition: imgui.cpp:4332
static ImGuiWindow * FindHoveredWindow(ImVec2 pos, bool excluding_childs)
Definition: imgui.cpp:2386
IMGUI_API bool IsMouseHoveringBox(const ImVec2 &box_min, const ImVec2 &box_max)
Definition: imgui.cpp:2426
float ChildWindowRounding
Definition: imgui.h:527
IMGUI_API void ClearInputData()
Definition: imgui.cpp:7234
static float ImLerp(float a, float b, float t)
Definition: imgui.cpp:640
static ImVec2 & operator-=(ImVec2 &lhs, const ImVec2 &rhs)
Definition: imgui.cpp:626
IMGUI_API void PushTextureID(const ImTextureID &texture_id)
Definition: imgui.cpp:6919
IMGUI_API void Spacing()
Definition: imgui.cpp:6476
static void ShowExampleAppConsole(bool *opened)
Definition: imgui.cpp:9645
ImVec2 pos
Definition: imgui.h:811
float x
Definition: imgui.h:63
static bool InputFloatN(const char *label, float *v, int components, int decimal_precision)
Definition: imgui.cpp:5904
IMGUI_API void appendv(const char *fmt, va_list args)
Definition: imgui.cpp:1432
IMGUI_API void SetWindowPos(const ImVec2 &pos, ImGuiSetCond cond=0)
Definition: imgui.cpp:3510
static bool SliderFloatN(const char *label, float v[3], int components, float v_min, float v_max, const char *display_format, float power)
Definition: imgui.cpp:4889
IMGUI_API void PopTextureID()
Definition: imgui.cpp:6925
IMGUI_API void SetCursorPos(const ImVec2 &pos)
Definition: imgui.cpp:3721
#define IM_ASSERT(_EXPR)
Definition: imconfig.h:16
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond=0)
Definition: imgui.cpp:4562
void(* ImDrawCallback)(const ImDrawList *parent_list, const ImDrawCmd *cmd)
Definition: imgui.h:795
const float PI
Definition: imgui.cpp:602
IMGUI_API void PopStyleColor(int count=1)
Definition: imgui.cpp:3345
static void ApplyNumericalTextInput(const char *buf, float *v)
Definition: imgui.cpp:4608
static ImVec2 & operator*=(ImVec2 &lhs, const float rhs)
Definition: imgui.cpp:627
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b)
Definition: imgui.cpp:790
IMGUI_API void CalcListClipping(int items_count, float items_height, int *out_items_display_start, int *out_items_display_end)
Definition: imgui.cpp:2358
IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiSetCond cond=0)
Definition: imgui.cpp:3574
IMGUI_API void SetFallbackChar(ImWchar c)
Definition: imgui.cpp:7744
signed short Height
Definition: imgui.h:938
IMGUI_API void NextColumn()
Definition: imgui.cpp:6575
const char * begin() const
Definition: imgui.h:662
Font interface.
Definition: Font.h:16
IMGUI_API bool IsMouseHoveringAnyWindow()
Definition: imgui.cpp:2438
static ImVec2 operator/(const ImVec2 &lhs, const ImVec2 rhs)
Definition: imgui.cpp:624
IMGUI_API ImVec2 GetCursorPos()
Definition: imgui.cpp:3705
IMGUI_API void split(char separator, ImVector< TextRange > &out)
Definition: imgui.cpp:1354
IMGUI_API void GetTexDataAsRGBA32(unsigned char **out_pixels, int *out_width, int *out_height, int *out_bytes_per_pixel=NULL)
Definition: imgui.cpp:7294
IMGUI_API bool ColorEdit3(const char *label, float col[3])
Definition: imgui.cpp:6284
static ptrdiff_t ImTextStrFromUtf8(ImWchar *buf, size_t buf_size, const char *in_text, const char *in_text_end, const char **in_remaining=NULL)
Definition: imgui.cpp:7822
IMGUI_API void SetColumnOffset(int column_index, float offset_x)
Definition: imgui.cpp:6636
void * TexID
Definition: imgui.h:905
IMGUI_API const char * CalcWordWrapPositionA(float scale, const char *text, const char *text_end, float wrap_width) const
Definition: imgui.cpp:7926
IMGUI_API void LogToTTY(int max_depth=-1)
Definition: imgui.cpp:4228
bool MouseClicked[5]
Definition: imgui.h:621
IMGUI_API bool IsMouseClicked(int button, bool repeat=false)
Definition: imgui.cpp:2474
unsigned int vtx_count
Definition: imgui.h:800
IMGUI_API float GetTextLineHeight()
Definition: imgui.cpp:3666
signed short Width
Definition: imgui.h:938
IMGUI_API void AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners=0x0F)
Definition: imgui.cpp:7021
static void PushClipRect(const ImVec4 &clip_rect, bool clipped=true)
Definition: imgui.cpp:1989
static bool Items_SingleStringGetter(void *data, int idx, const char **out_text)
Definition: imgui.cpp:5962
static ImGuiWindow * FindWindowByName(const char *name)
Definition: imgui.cpp:2667
IMGUI_API void TextWrapped(const char *fmt,...)
Definition: imgui.cpp:3832
IMGUI_API void * GetInternalState()
Definition: imgui.cpp:1718
static bool is_separator(unsigned int c)
Definition: imgui.cpp:5270
static float * GetStyleVarFloatAddr(ImGuiStyleVar idx)
Definition: imgui.cpp:3358
static void ShowExampleAppManipulatingWindowTitle(bool *opened)
Definition: imgui.cpp:9301
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
IMGUI_API void End()
Definition: imgui.cpp:3137
int ImGuiColorEditMode
Definition: imgui.h:43
IMGUI_API bool SliderFloat2(const char *label, float v[2], float v_min, float v_max, const char *display_format="%.3f", float power=1.0f)
Definition: imgui.cpp:4924
int TexWidth
Definition: imgui.h:908
IMGUI_API void SetTooltipV(const char *fmt, va_list args)
Definition: imgui.cpp:2540
static void AddWindowToSortedBuffer(ImGuiWindow *window, ImVector< ImGuiWindow * > &sorted_windows)
Definition: imgui.cpp:1972
float Alpha
Definition: imgui.h:523
unsigned short x0
Definition: stb_truetype.h:499
IMGUI_API float GetCursorPosY()
Definition: imgui.cpp:3716
IMGUI_API void ListBoxFooter()
Definition: imgui.cpp:6205
static void ItemSize(ImVec2 size, ImVec2 *adjust_start_offset=NULL)
Definition: imgui.cpp:6486
IMGUI_API bool SliderInt2(const char *label, int v[2], int v_min, int v_max, const char *display_format="%.0f")
Definition: imgui.cpp:4974
IMGUI_API bool TreeNodeV(const char *str_id, const char *fmt, va_list args)
Definition: imgui.cpp:4502
IMGUI_API float CalcItemWidth()
Definition: imgui.cpp:3262
IMGUI_API ImVec2 GetMousePos()
Definition: imgui.cpp:2499
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui.cpp:5254
IMGUI_API void TreePush(const char *str_id=NULL)
Definition: imgui.cpp:6757
static unsigned char * stb__barrier2
Definition: imgui.cpp:9725
int(* ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data)
Definition: imgui.h:48
IMGUI_API bool SliderFloat(const char *label, float *v, float v_min, float v_max, const char *display_format="%.3f", float power=1.0f)
Definition: imgui.cpp:4654
IMGUI_API const ImWchar * GetGlyphRangesJapanese()
Definition: imgui.cpp:7640
const char * begin() const
Definition: imgui.h:690
Definition: imgui.h:61
IMGUI_API void BeginChildFrame(ImGuiID id, const ImVec2 &size)
Definition: imgui.cpp:2651
IMGUI_API void SetCursorPosX(float x)
Definition: imgui.cpp:3728
IMGUI_API bool IsAnyItemActive()
Definition: imgui.cpp:2521
static void ShowExampleAppFixedOverlay(bool *opened)
Definition: imgui.cpp:9285
STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
static void LoadSettings()
Definition: imgui.cpp:1620
IMGUI_API bool IsMouseHoveringWindow()
Definition: imgui.cpp:2431
IMGUI_API void SetInternalState(void *state, bool construct=false)
Definition: imgui.cpp:1728
bool KeyShift
Definition: imgui.h:600
float FontSize
Definition: imgui.h:928
ImVec2 FramePadding
Definition: imgui.h:528
size_t size() const
Definition: imgui.h:692
static int ImUpperPowerOfTwo(int v)
Definition: imgui.cpp:457
size_t size() const
Definition: imgui.h:100
IMGUI_API void Shutdown()
Definition: imgui.cpp:1909
IMGUI_API void PushClipRect(const ImVec4 &clip_rect)
Definition: imgui.cpp:6892
static ImGuiIniData * AddWindowSettings(const char *name)
Definition: imgui.cpp:1605
static void SetWindowSize(ImGuiWindow *window, const ImVec2 &size, ImGuiSetCond cond)
Definition: imgui.cpp:3529
#define IM_ARRAYSIZE(_ARR)
Definition: imgui.cpp:599
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiSetCond cond=0)
Definition: imgui.cpp:3606
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING *obj, int line_start_idx, int char_idx)
Definition: imgui.cpp:5255
IMGUI_API ImVec2 GetContentRegionMax()
Definition: imgui.cpp:3633
ImVec4 clip_rect
Definition: imgui.h:801
stbtt_packedchar * chardata_for_range
Definition: stb_truetype.h:546
char front() const
Definition: imgui.h:665
bool KeyCtrl
Definition: imgui.h:599
IMGUI_API bool InputFloat4(const char *label, float v[4], int decimal_precision=-1)
Definition: imgui.cpp:5949
float TreeNodeSpacing
Definition: imgui.h:535
IMGUI_API void PopStyleVar(int count=1)
Definition: imgui.cpp:3412
static bool IsMouseHoveringBox(const ImGuiAabb &bb)
Definition: imgui.cpp:2408
static int STB_TEXTEDIT_KEYTOTEXT(int key)
Definition: imgui.cpp:5256
static int ImStricmp(const char *str1, const char *str2)
Definition: imgui.cpp:644
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v)
Definition: imgui.cpp:768
IMGUI_API void SetCursorPosY(float y)
Definition: imgui.cpp:3735
IMGUI_API void LogText(const char *fmt,...)
Definition: imgui.cpp:2118
static int ImStrnicmp(const char *str1, const char *str2, int count)
Definition: imgui.cpp:651
static bool IsClipped(const ImGuiAabb &bb)
Definition: imgui.cpp:6512
static void stb__lit(unsigned char *data, unsigned int length)
Definition: imgui.cpp:9737
IMGUI_API ImFont * AddFontDefault()
Definition: imgui.cpp:7320
static void ShowExampleAppAutoResize(bool *opened)
Definition: imgui.cpp:9268
ImVec2 WindowMinSize
Definition: imgui.h:525
IMGUI_API void TextColoredV(const ImVec4 &col, const char *fmt, va_list args)
Definition: imgui.cpp:3810
STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context)
IMGUI_API bool SmallButton(const char *label)
Definition: imgui.cpp:4086
float GrabMinSize
Definition: imgui.h:538
static int ImClamp(int v, int mn, int mx)
Definition: imgui.cpp:636
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border=true, float rounding=0.0f)
Definition: imgui.cpp:2280
IMGUI_API void Clear()
Definition: imgui.cpp:1217
static ImGuiState GImDefaultState
Definition: imgui.cpp:1117
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
void * user_callback_data
Definition: imgui.h:804
static ImGuiWindow * CreateNewWindow(const char *name, ImVec2 size, ImGuiWindowFlags flags)
Definition: imgui.cpp:2678
IMGUI_API ImFont * GetWindowFont()
Definition: imgui.cpp:3685
IMGUI_API ImVec2 GetWindowContentRegionMax()
Definition: imgui.cpp:3657
static void stb__match(unsigned char *data, unsigned int length)
Definition: imgui.cpp:9728
IMGUI_API size_t GetInternalStateSize()
Definition: imgui.cpp:1723
static const ImVec2 TEX_ATLAS_SIZE(32, 32)
IMGUI_API bool CheckboxFlags(const char *label, unsigned int *flags, unsigned int flags_value)
Definition: imgui.cpp:5175
IMGUI_API bool IsClipped(const ImVec2 &item_size)
Definition: imgui.cpp:6522
unsigned short ImWchar
Definition: imgui.h:37
IMGUI_API ImVec2 GetWindowContentRegionMin()
Definition: imgui.cpp:3651
IMGUI_API void Color(const char *prefix, const ImVec4 &v)
Definition: imgui.cpp:6816
static const ImVec2 TEX_ATLAS_SIZE_MOUSE_CURSOR(12, 19)
ImGuiInputTextFlags Flags
Definition: imgui.h:746
int ImGuiInputTextFlags
Definition: imgui.h:46
IMGUI_API float GetTextLineHeightWithSpacing()
Definition: imgui.cpp:3672
static ImVec2 & operator+=(ImVec2 &lhs, const ImVec2 &rhs)
Definition: imgui.cpp:625
static bool ImCharIsSpace(int c)
Definition: imgui.cpp:458
IMGUI_API int GetFrameCount()
Definition: imgui.cpp:2559
IMGUI_API void * GetVoidPtr(ImGuiID key) const
Definition: imgui.cpp:1261
IMGUI_API bool InputFloat2(const char *label, float v[2], int decimal_precision=-1)
Definition: imgui.cpp:5939
IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2 &pos)
Definition: imgui.cpp:2444
void clear()
Definition: imgui.h:108
IMGUI_API void AddText(ImFont *font, float font_size, const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end=NULL, float wrap_width=0.0f, const ImVec2 *cpu_clip_max=NULL)
Definition: imgui.cpp:7153
IMGUI_API float GetCursorPosX()
Definition: imgui.cpp:3711
IMGUI_API float GetColumnOffset(int column_index=-1)
Definition: imgui.cpp:6619
IMGUI_API bool ColorEdit4(const char *label, float col[4], bool show_alpha=true)
Definition: imgui.cpp:6300
IMGUI_API bool Build()
Definition: imgui.cpp:7378
Definition: imgui.h:50
IMGUI_API bool ColorButton(const ImVec4 &col, bool small_height=false, bool outline_border=true)
Definition: imgui.cpp:6253
IMGUI_API bool InvisibleButton(const char *str_id, const ImVec2 &size)
Definition: imgui.cpp:4115
STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels)
unsigned char * pixels
Definition: stb_truetype.h:589
Definition: imgui.h:925
IMGUI_API void AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners=0x0F)
Definition: imgui.cpp:7053
IMGUI_API void TextColored(const ImVec4 &col, const char *fmt,...)
Definition: imgui.cpp:3817
IMGUI_API bool GetWindowCollapsed()
Definition: imgui.cpp:3580
int ImGuiWindowFlags
Definition: imgui.h:44
IMGUI_API bool InputFloat(const char *label, float *v, float step=0.0f, float step_fast=0.0f, int decimal_precision=-1, ImGuiInputTextFlags extra_flags=0)
Definition: imgui.cpp:5419
IMGUI_API void AlignFirstTextHeightToWidgets()
Definition: imgui.cpp:3941
IMGUI_API ImDrawList * GetWindowDrawList()
Definition: imgui.cpp:3679
IMGUI_API void GetDefaultFontData(const void **fnt_data, unsigned int *fnt_size, const void **png_data, unsigned int *png_size)
Definition: imgui.cpp:7267
IMGUI_API float GetScrollPosY()
Definition: imgui.cpp:3754
IMGUI_API void Render()
Definition: imgui.cpp:2012
IMGUI_API bool IsLoaded() const
Definition: imgui.h:956
IMGUI_API bool ListBox(const char *label, int *current_item, const char **items, int items_count, int height_in_items=-1)
Definition: imgui.cpp:6216
IMGUI_API void ColorEditMode(ImGuiColorEditMode mode)
Definition: imgui.cpp:6441
IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiTextEditCallback callback=NULL, void *user_data=NULL)
Definition: imgui.cpp:5577
void DeleteChars(int pos, int bytes_count)
Definition: imgui.cpp:5490
#define assert(x)
Definition: global.h:124
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING *obj)
Definition: imgui.cpp:5253
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val)
Definition: imgui.cpp:3385
IMGUI_API ImFont * AddFontFromFileTTF(const char *filename, float size_pixels, const ImWchar *glyph_ranges=NULL, int font_no=0)
Definition: imgui.cpp:7338
static size_t ImStrlenW(const ImWchar *str)
Definition: imgui.cpp:666
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0), bool repeat_when_held=false)
Definition: imgui.cpp:4055
IMGUI_API void SetKeyboardFocusHere(int offset=0)
Definition: imgui.cpp:3772
IMGUI_API void PopTextWrapPos()
Definition: imgui.cpp:3328
static ImWchar STB_TEXTEDIT_NEWLINE
Definition: imgui.cpp:5257
iterator end()
Definition: imgui.h:111
IMGUI_API bool IsItemActive()
Definition: imgui.cpp:2510
IMGUI_API int * GetIntRef(ImGuiID key, int default_val=0)
Definition: imgui.cpp:1270
IMGUI_API void AddVtx(const ImVec2 &pos, ImU32 col)
Definition: imgui.cpp:6943
static void RenderText(ImVec2 pos, const char *text, const char *text_end=NULL, bool hide_text_after_hash=true)
Definition: imgui.cpp:2205
IMGUI_API ImVec2 GetCursorScreenPos()
Definition: imgui.cpp:3742
static void SetFont(ImFont *font)
Definition: imgui.cpp:3278
static void SetWindowCollapsed(ImGuiWindow *window, bool collapsed, ImGuiSetCond cond)
Definition: imgui.cpp:3563
static bool Items_ArrayGetter(void *data, int idx, const char **out_text)
Definition: imgui.cpp:5954
static int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:7914
IMGUI_API void SetWindowFontScale(float scale)
Definition: imgui.cpp:3697
ImVec2 MousePos
Definition: imgui.h:595
IMGUI_API ImVec2 CalcTextSizeW(float size, float max_width, const ImWchar *text_begin, const ImWchar *text_end, const ImWchar **remaining=NULL) const
Definition: imgui.cpp:8101
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0=ImVec2(0, 0), const ImVec2 &uv1=ImVec2(1, 1), int frame_padding=-1, const ImVec4 &bg_col=ImVec4(0, 0, 0, 1), const ImVec4 &tint_col=ImVec4(1, 1, 1, 1))
Definition: imgui.cpp:4191
IMGUI_API void Clear()
Definition: imgui.cpp:6842
float FrameRounding
Definition: imgui.h:529
IMGUI_API float GetFloat(ImGuiID key, float default_val=0.0f) const
Definition: imgui.cpp:1253
IMGUI_API ImVec2 GetItemBoxMin()
Definition: imgui.cpp:2527
static ImGuiWindow * GetCurrentWindow()
Definition: imgui.cpp:1185
IMGUI_API void ClearTexData()
Definition: imgui.cpp:7245
int ImGuiStyleVar
Definition: imgui.h:41
static const unsigned int proggy_clean_ttf_compressed_size
Definition: imgui.cpp:9832
void push_back(const value_type &v)
Definition: imgui.h:130
static bool IsKeyPressedMap(ImGuiKey key, bool repeat=true)
Definition: imgui.cpp:2449
IMGUI_API void PopAllowKeyboardFocus()
Definition: imgui.cpp:3316
IMGUI_API float GetColumnWidth(int column_index=-1)
Definition: imgui.cpp:6653
int ImGuiKey
Definition: imgui.h:42
Definition: imgui.h:546
IMGUI_API bool SliderFloat3(const char *label, float v[3], float v_min, float v_max, const char *display_format="%.3f", float power=1.0f)
Definition: imgui.cpp:4929
static void ShowExampleAppLongText(bool *opened)
Definition: imgui.cpp:9651
static bool SliderIntN(const char *label, int v[3], int components, int v_min, int v_max, const char *display_format)
Definition: imgui.cpp:4939
static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_BLACK(1, 3)
#define stb__in3(x)
Definition: imgui.cpp:9747
IMGUI_API bool SliderFloat4(const char *label, float v[4], float v_min, float v_max, const char *display_format="%.3f", float power=1.0f)
Definition: imgui.cpp:4934
IMGUI_API void AddCircleFilled(const ImVec2 &centre, float radius, ImU32 col, int num_segments=12)
Definition: imgui.cpp:7135
IMGUI_API void SetCursorScreenPos(const ImVec2 &pos)
Definition: imgui.cpp:3748
IMGUI_API void PopID()
Definition: imgui.cpp:4588
static size_t ImFormatStringV(char *buf, size_t buf_size, const char *fmt, va_list args)
Definition: imgui.cpp:750
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiSetCond cond=0)
Definition: imgui.cpp:3613
float V0
Definition: imgui.h:940
IMGUI_API void Bullet()
Definition: imgui.cpp:4445
IMGUI_API ImGuiIO & GetIO()
Definition: imgui.cpp:1736
signed short XOffset
Definition: imgui.h:939
static void RegisterAliveId(const ImGuiID &id)
Definition: imgui.cpp:1207
ImDrawCallback user_callback
Definition: imgui.h:803
static void Plot(ImGuiPlotType plot_type, const char *label, float(*values_getter)(void *data, int idx), void *data, int values_count, int values_offset, const char *overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
Definition: imgui.cpp:4995
const char * end() const
Definition: imgui.h:691
static void LogText(const ImVec2 &ref_pos, const char *text, const char *text_end=NULL)
Definition: imgui.cpp:2139
static void RenderCollapseTriangle(ImVec2 p_min, bool opened, float scale=1.0f, bool shadow=false)
Definition: imgui.cpp:2294
IMGUI_API void EndTooltip()
Definition: imgui.cpp:2571
IMGUI_API void Clear()
Definition: imgui.cpp:7255
IMGUI_API void AddCircle(const ImVec2 &centre, float radius, ImU32 col, int num_segments=12)
Definition: imgui.cpp:7119
#define STR_NEWLINE
Definition: imgui.cpp:614
bool empty() const
Definition: imgui.h:664
float z
Definition: imgui.h:63
IMGUI_API void AddDrawCmd()
Definition: imgui.cpp:6851
IMGUI_API void BulletText(const char *fmt,...)
Definition: imgui.cpp:4493
iterator insert(const_iterator it, const value_type &v)
Definition: imgui.h:134
IMGUI_API bool GetWindowIsFocused()
Definition: imgui.cpp:3477
static bool IsHovered(const ImGuiAabb &bb, const ImGuiID &id)
Definition: imgui.cpp:3987
IMGUI_API void SetAllInt(int val)
Definition: imgui.cpp:1321
ImVec2 ItemSpacing
Definition: imgui.h:530
ImWchar Codepoint
Definition: imgui.h:936
IMGUI_API void PopClipRect()
Definition: imgui.cpp:6898
IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiSetCond cond=0)
Definition: imgui.cpp:3620
static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length)
Definition: imgui.cpp:9798
IMGUI_API void PushFont(ImFont *font)
Definition: imgui.cpp:3289
IMGUI_API const ImWchar * GetGlyphRangesChinese()
Definition: imgui.cpp:7626
float WindowFillAlphaDefault
Definition: imgui.h:534
IMGUI_API void TreePop()
Definition: imgui.cpp:6777
IMGUI_API ImGuiStyle & GetStyle()
Definition: imgui.cpp:1741
IMGUI_API void SetTooltip(const char *fmt,...)
Definition: imgui.cpp:2546
static unsigned int stb_decompress_length(unsigned char *input)
Definition: imgui.cpp:9720
float w
Definition: imgui.h:63
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
IMGUI_API void PushAllowKeyboardFocus(bool v)
Definition: imgui.cpp:3310
#define va_copy(dest, src)
Definition: imgui.cpp:1428
ImVec2 uv
Definition: imgui.h:812
static float f1
Definition: binary.cpp:29
IMGUI_API void Columns(int count=1, const char *id=NULL, bool border=true)
Definition: imgui.cpp:6674
static int ImMax(int lhs, int rhs)
Definition: imgui.cpp:631
static void RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width)
Definition: imgui.cpp:2235
IMGUI_API void AddArc(const ImVec2 &center, float rad, ImU32 col, int a_min, int a_max, bool tris=false, const ImVec2 &third_point_offset=ImVec2(0, 0))
Definition: imgui.cpp:6985
static bool ButtonBehaviour(const ImGuiAabb &bb, const ImGuiID &id, bool *out_hovered, bool *out_held, bool allow_key_modifiers, bool repeat=false, bool pressed_on_click=false)
Definition: imgui.cpp:4002
static float ImLengthSqr(const ImVec2 &lhs)
Definition: imgui.cpp:642
stbrp_coord h
Definition: stb_rect_pack.h:87
IMGUI_API void SetInt(ImGuiID key, int val)
Definition: imgui.cpp:1288
IMGUI_API void BuildLookupTable()
Definition: imgui.cpp:7700
IMGUI_API void RenderCustomTexData()
Definition: imgui.cpp:7551
IMGUI_API void AddCallback(ImDrawCallback callback, void *callback_data)
Definition: imgui.cpp:6862
IMGUI_API void SameLine(int column_x=0, int spacing_w=-1)
Definition: imgui.cpp:6551
static ImVec2 operator*(const ImVec2 &lhs, const float rhs)
Definition: imgui.cpp:619
static int ImTextCharToUtf8(char *buf, size_t buf_size, unsigned int in_char)
Definition: imgui.cpp:7857
IMGUI_API void ShowStyleEditor(ImGuiStyle *ref=NULL)
Definition: imgui.cpp:8423
IMGUI_API void LogButtons()
Definition: imgui.cpp:4304
IMGUI_API void EndChild()
Definition: imgui.cpp:2623
float baseline_y_delta
Definition: stb_textedit.h:336
static void MarkSettingsDirty()
Definition: imgui.cpp:1708
static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
Definition: imgui.cpp:9767
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow *r, STB_TEXTEDIT_STRING *obj, int line_start_idx)
Definition: imgui.cpp:5258
ImVec2 AutoFitPadding
Definition: imgui.h:533
IMGUI_API bool IsItemHovered()
Definition: imgui.cpp:2504
IMGUI_API void MemFree(void *ptr)
Definition: imgui.cpp:1587
bool MouseDown[5]
Definition: imgui.h:596
static const unsigned int proggy_clean_ttf_compressed_data[9584/4]
Definition: imgui.cpp:9833
IMGUI_API ImGuiIO()
Definition: imgui.cpp:555
IMGUI_API void SetFloat(ImGuiID key, float val)
Definition: imgui.cpp:1299
IMGUI_API void PushTextWrapPos(float wrap_pos_x=0.0f)
Definition: imgui.cpp:3322
STBTT_DEF void stbtt_PackEnd(stbtt_pack_context *spc)
ImTextureID texture_id
Definition: imgui.h:802
Definition: imgui.h:768
IMGUI_API int GetColumnsCount()
Definition: imgui.cpp:6613
IMGUI_API float * GetFloatRef(ImGuiID key, float default_val=0)
Definition: imgui.cpp:1278
IMGUI_API void ShowUserGuide()
Definition: imgui.cpp:8399
stbrp_coord y
Definition: stb_rect_pack.h:90
IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4 &in)
Definition: imgui.cpp:757
static int ImMin(int lhs, int rhs)
Definition: imgui.cpp:630
static float f2
Definition: binary.cpp:30
IMGUI_API void SetVoidPtr(ImGuiID key, void *val)
Definition: imgui.cpp:1310
float Scale
Definition: imgui.h:929
static unsigned char * stb__dout
Definition: imgui.cpp:9727
ImFontAtlas * ContainerAtlas
Definition: imgui.h:942
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
ImVec2 ItemInnerSpacing
Definition: imgui.h:531
IMGUI_API void UpdateClipRect()
Definition: imgui.cpp:6878
stbrp_coord x
Definition: stb_rect_pack.h:90
static float Plot_ArrayGetter(void *data, int idx)
Definition: imgui.cpp:5099
#define stb__in4(x)
Definition: imgui.cpp:9748
ImVec4 Colors[ImGuiCol_COUNT]
Definition: imgui.h:539
IMGUI_API ImVec2 CalcTextSize(const char *text, const char *text_end=NULL, bool hide_text_after_double_hash=false, float wrap_width=-1.0f)
Definition: imgui.cpp:2324
float y
Definition: imgui.h:63
static size_t ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
Definition: imgui.cpp:740
ImVector< ImFont * > Fonts
Definition: imgui.h:912
IMGUI_API void AddVtxUV(const ImVec2 &pos, ImU32 col, const ImVec2 &uv)
Definition: imgui.cpp:6951
IMGUI_API bool Combo(const char *label, int *current_item, const char **items, int items_count, int height_in_items=-1)
Definition: imgui.cpp:5983
float V1
Definition: imgui.h:940
IMGUI_API void * MemAlloc(size_t sz)
Definition: imgui.cpp:1582
IMGUI_API void AddVtxLine(const ImVec2 &a, const ImVec2 &b, ImU32 col)
Definition: imgui.cpp:6960
float U1
Definition: imgui.h:940
IMGUI_API const ImWchar * GetGlyphRangesDefault()
Definition: imgui.cpp:7616
static ptrdiff_t ImTextStrToUtf8(char *buf, size_t buf_size, const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:7901
IMGUI_API void Text(const char *fmt,...)
Definition: imgui.cpp:3802
IMGUI_API void append(const char *fmt,...)
Definition: imgui.cpp:1453
static ImVec2 operator-(const ImVec2 &lhs, const ImVec2 &rhs)
Definition: imgui.cpp:622
ImGuiPlotType
Definition: imgui.cpp:4989
iterator erase(const_iterator it)
Definition: imgui.h:133
static ImGuiWindow * GetParentWindow()
Definition: imgui.cpp:1193
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
static ImColor HSV(float h, float s, float v, float a=1.0f)
Definition: imgui.h:778
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &uv0, const ImVec2 &uv1, ImU32 col=0xFFFFFFFF)
Definition: imgui.cpp:7178
IMGUI_API bool IsMouseDoubleClicked(int button)
Definition: imgui.cpp:2492
static void FocusWindow(ImGuiWindow *window)
Definition: imgui.cpp:3227
IMGUI_API void SetScrollPosHere()
Definition: imgui.cpp:3766
static void SaveSettings()
Definition: imgui.cpp:1666
const char * end() const
Definition: imgui.h:663
IMGUI_API int GetColumnIndex()
Definition: imgui.cpp:6607
static void GetDefaultCompressedFontDataTTF(const void **ttf_compressed_data, unsigned int *ttf_compressed_size)
Definition: imgui.cpp:10037
IMGUI_API void Build()
Definition: imgui.cpp:1372
void InsertChars(int pos, const char *text, const char *text_end=NULL)
Definition: imgui.cpp:5506
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING *obj, int pos, int n)
Definition: imgui.cpp:5272
int TexHeight
Definition: imgui.h:909
bool empty() const
Definition: imgui.h:99
static const char * FindTextDisplayEnd(const char *text, const char *text_end=NULL)
Definition: imgui.cpp:2107
float ScrollbarWidth
Definition: imgui.h:537
IMGUI_API void RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4 &clip_rect, const char *text_begin, const char *text_end, ImDrawVert *&out_vertices, float wrap_width=0.0f, const ImVec2 *cpu_clip_max=NULL) const
Definition: imgui.cpp:8145
IMGUI_API void SetWindowSize(const ImVec2 &size, ImGuiSetCond cond=0)
Definition: imgui.cpp:3550
float WindowRounding
Definition: imgui.h:526
IMGUI_API bool Selectable(const char *label, bool selected, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui.cpp:6108
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
Definition: imgui.cpp:8389
static void SetClipboardTextFn_DefaultImpl(const char *text)
Definition: imgui.cpp:8348
IMGUI_API void Separator()
Definition: imgui.cpp:6448
static int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:7841
void clear()
Definition: imgui.h:694
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0=ImVec2(0, 0), const ImVec2 &uv1=ImVec2(1, 1), const ImVec4 &tint_col=ImVec4(1, 1, 1, 1), const ImVec4 &border_col=ImVec4(0, 0, 0, 0))
Definition: imgui.cpp:4163
IMGUI_API ImVec2 GetWindowPos()
Definition: imgui.cpp:3490
IMGUI_API const char * GetStyleColName(ImGuiCol idx)
Definition: imgui.cpp:3428
static char * ImStrdup(const char *str)
Definition: imgui.cpp:658
static const float scale
Definition: Sprite.cpp:15
static void PopClipRect()
Definition: imgui.cpp:2005
IMGUI_API ~ImFontAtlas()
Definition: imgui.cpp:7229
IMGUI_API bool SliderInt4(const char *label, int v[4], int v_min, int v_max, const char *display_format="%.0f")
Definition: imgui.cpp:4984
ImU32 col
Definition: imgui.h:813
static void PushColumnClipRect(int column_index=-1)
Definition: imgui.cpp:6663
float x
Definition: imgui.h:52
static bool ImLoadFileToMemory(const char *filename, const char *file_open_mode, void **out_file_data, size_t *out_file_size, size_t padding_bytes=0)
Definition: imgui.cpp:819
IMGUI_API void LogFinish()
Definition: imgui.cpp:4279
static ImVec2 operator+(const ImVec2 &lhs, const ImVec2 &rhs)
Definition: imgui.cpp:621
IMGUI_API void ReserveVertices(unsigned int vtx_count)
Definition: imgui.cpp:6932
static ImGuiState * GImGui
Definition: imgui.cpp:1118
ImGuiTextFilter(const char *default_filter="")
Definition: imgui.cpp:1330
ImU32 ImGuiID
Definition: imgui.h:39
IMGUI_API float GetTime()
Definition: imgui.cpp:2554
ImGuiInputTextFlags EventFlag
Definition: imgui.h:745
iterator begin()
Definition: imgui.h:109
IMGUI_API float GetWindowFontSize()
Definition: imgui.cpp:3691
int ImGuiSetCond
Definition: imgui.h:45
IMGUI_API void TextUnformatted(const char *text, const char *text_end=NULL)
Definition: imgui.cpp:3840
value_type * iterator
Definition: imgui.h:93
STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
IMGUI_API void EndChildFrame()
Definition: imgui.cpp:2660
value_type & front()
Definition: imgui.h:113
unsigned short y1
Definition: stb_truetype.h:499
void resize(size_t new_size)
Definition: imgui.h:119
IMGUI_API float GetScrollMaxY()
Definition: imgui.cpp:3760
IMGUI_API void LabelTextV(const char *label, const char *fmt, va_list args)
Definition: imgui.cpp:3954
IMGUI_API bool SliderAngle(const char *label, float *v, float v_degrees_min=-360.0f, float v_degrees_max=+360.0f)
Definition: imgui.cpp:4870
IMGUI_API void NewFrame()
Definition: imgui.cpp:1746
bool MouseDoubleClicked[5]
Definition: imgui.h:624
float y
Definition: imgui.h:52
IMGUI_API void BulletTextV(const char *fmt, va_list args)
Definition: imgui.cpp:4468
IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char *text_begin, const char *text_end=NULL, const char **remaining=NULL) const
Definition: imgui.cpp:8015
IMGUI_API void LogToClipboard(int max_depth=-1)
Definition: imgui.cpp:4265
static unsigned char * stb__barrier4
Definition: imgui.cpp:9725
IMGUI_API ImGuiStyle()
Definition: imgui.cpp:491
int ImGuiCol
Definition: imgui.h:40
IMGUI_API void LabelText(const char *label, const char *fmt,...)
Definition: imgui.cpp:3979
IMGUI_API void LogToFile(int max_depth=-1, const char *filename=NULL)
Definition: imgui.cpp:4243
static unsigned char * stb__barrier3
Definition: imgui.cpp:9725
IMGUI_API bool ListBoxHeader(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui.cpp:6165
IMGUI_API ImGuiStorage * GetStateStorage()
Definition: imgui.cpp:3785
signed short YOffset
Definition: imgui.h:939
static const char * ImStristr(const char *haystack, const char *needle, const char *needle_end)
Definition: imgui.cpp:673
IMGUI_API ImGuiID GetID(const char *str_id)
Definition: imgui.cpp:4594
IMGUI_API ImFontAtlas()
Definition: imgui.cpp:7220
int first_unicode_char_in_range
Definition: stb_truetype.h:544
IMGUI_API void ShowTestWindow(bool *open=NULL)
Definition: imgui.cpp:8529
IMGUI_API void PlotLines(const char *label, const float *values, int values_count, int values_offset=0, const char *overlay_text=NULL, float scale_min=FLT_MAX, float scale_max=FLT_MAX, ImVec2 graph_size=ImVec2(0, 0), size_t stride=sizeof(float))
Definition: imgui.cpp:5106
stbrp_coord w
Definition: stb_rect_pack.h:87
IMGUI_API void UpdateTextureID()
Definition: imgui.cpp:6905
static void SetActiveId(ImGuiID id)
Definition: imgui.cpp:1200
IMGUI_API bool InputFloat3(const char *label, float v[3], int decimal_precision=-1)
Definition: imgui.cpp:5944
unsigned short stbrp_coord
Definition: stb_rect_pack.h:56
IMGUI_API void SetStateStorage(ImGuiStorage *tree)
Definition: imgui.cpp:3779
static int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end)
Definition: imgui.cpp:7764
ImVec2 TouchExtraPadding
Definition: imgui.h:532
IMGUI_API bool BeginChild(const char *str_id, const ImVec2 &size=ImVec2(0, 0), bool border=false, ImGuiWindowFlags extra_flags=0)
Definition: imgui.cpp:2577
IMGUI_API bool Begin(const char *name="Debug", bool *p_opened=NULL, const ImVec2 &initial_size=ImVec2(0, 0), float bg_alpha=-1.0f, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:2735
bool PassFilter(const char *val) const
Definition: imgui.cpp:1389
IMGUI_API bool SliderInt3(const char *label, int v[3], int v_min, int v_max, const char *display_format="%.0f")
Definition: imgui.cpp:4979
IMGUI_API ImFont * AddFontFromMemoryTTF(void *in_ttf_data, size_t in_ttf_data_size, float size_pixels, const ImWchar *glyph_ranges=NULL, int font_no=0)
Definition: imgui.cpp:7354
static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING *obj, int pos, const ImWchar *new_text, int new_text_len)
Definition: imgui.cpp:5287
IMGUI_API bool InputInt(const char *label, int *v, int step=1, int step_fast=100, ImGuiInputTextFlags extra_flags=0)
Definition: imgui.cpp:5479
IMGUI_API void TextV(const char *fmt, va_list args)
Definition: imgui.cpp:3791
IMGUI_API bool IsKeyPressed(int key_index, bool repeat=true)
Definition: imgui.cpp:2456
ImFontAtlas * Fonts
Definition: imgui.h:562
unsigned short x1
Definition: stb_truetype.h:499
IMGUI_API void AddTriangleFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col)
Definition: imgui.cpp:7108
ImVec2 WindowPadding
Definition: imgui.h:524
IMGUI_API void Value(const char *prefix, bool b)
Definition: imgui.cpp:6787
IMGUI_API float GetWindowWidth()
Definition: imgui.cpp:3484
static ImFontAtlas GDefaultFontAtlas
Definition: imgui.cpp:553
static unsigned char * stb__barrier
Definition: imgui.cpp:9725
IMGUI_API void PopFont()
Definition: imgui.cpp:3301
IMGUI_API ImVec2 GetItemBoxMax()
Definition: imgui.cpp:2533
static void Scrollbar(ImGuiWindow *window)
Definition: imgui.cpp:3161
static void SetWindowPos(ImGuiWindow *window, const ImVec2 &pos, ImGuiSetCond cond)
Definition: imgui.cpp:3496
static unsigned char * stb_decompress_token(unsigned char *i)
Definition: imgui.cpp:9750
IMGUI_API ImFont()
Definition: imgui.cpp:7596
IMGUI_API void AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col)
Definition: imgui.cpp:6976
void Draw(const char *label="Filter (inc,-exc)", float width=-1.0f)
Definition: imgui.cpp:1344
unsigned char has_preferred_x
Definition: stb_textedit.h:317
void pop_back()
Definition: imgui.h:131
IMGUI_API bool SliderInt(const char *label, int *v, int v_min, int v_max, const char *display_format="%.0f")
Definition: imgui.cpp:4878
IMGUI_API void PushItemWidth(float item_width)
Definition: imgui.cpp:3250
void * ImTextureID
Definition: imgui.h:38
static ImVec2 * GetStyleVarVec2Addr(ImGuiStyleVar idx)
Definition: imgui.cpp:3372
IMGUI_API void AddInputCharacter(ImWchar c)
Definition: imgui.cpp:585
float U0
Definition: imgui.h:940
static ImVec4 GNullClipRect(-9999.0f,-9999.0f,+9999.0f,+9999.0f)
static void ShowExampleAppCustomRendering(bool *opened)
Definition: imgui.cpp:9328
ImVector< Glyph > Glyphs
Definition: imgui.h:943
IMGUI_API const Glyph * FindGlyph(unsigned short c) const
Definition: imgui.cpp:7750
IMGUI_API bool TreeNode(const char *str_label_id)
Definition: imgui.cpp:4557
void(* ImeSetInputScreenPosFn)(int x, int y)
Definition: imgui.h:588
static bool CloseWindowButton(bool *p_opened=NULL)
Definition: imgui.cpp:4134
static ImGuiIniData * FindWindowSettings(const char *name)
Definition: imgui.cpp:1592
IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4 &col)
Definition: imgui.cpp:3334
static ImU32 ImHash(const void *data, size_t data_size, ImU32 seed)
Definition: imgui.cpp:697
IMGUI_API void PushID(const char *str_id)
Definition: imgui.cpp:4569