imgui.cpp
Go to the documentation of this file.
1 // dear imgui, v1.67 WIP
2 // (main code and documentation)
3 
4 // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
5 // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
6 // Get latest version at https://github.com/ocornut/imgui
7 // Releases change-log at https://github.com/ocornut/imgui/releases
8 // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started
9 // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
10 
11 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
12 // See LICENSE.txt for copyright and licensing details (standard MIT License).
13 // This library is free but I need your support to sustain development and maintenance.
14 // Businesses: you can support continued maintenance and development via support contracts or sponsoring, see docs/README.
15 // Individuals: you can support continued maintenance and development via donations or Patreon https://www.patreon.com/imgui.
16 
17 // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
18 // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
19 // modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
20 // come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
21 // to a better solution or official support for them.
22 
23 /*
24 
25 Index of this file:
26 
27 DOCUMENTATION
28 
29 - MISSION STATEMENT
30 - END-USER GUIDE
31 - PROGRAMMER GUIDE (read me!)
32  - Read first.
33  - How to update to a newer version of Dear ImGui.
34  - Getting started with integrating Dear ImGui in your code/engine.
35  - This is how a simple application may look like (2 variations).
36  - This is how a simple rendering function may look like.
37  - Using gamepad/keyboard navigation controls.
38 - API BREAKING CHANGES (read me when you update!)
39 - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
40  - How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
41  - How can I display an image? What is ImTextureID, how does it works?
42  - How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.
43  - How can I use my own math types instead of ImVec2/ImVec4?
44  - How can I load a different font than the default?
45  - How can I easily use icons in my application?
46  - How can I load multiple fonts?
47  - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
48  - How can I interact with standard C++ types (such as std::string and std::vector)?
49  - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
50  - How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad)
51  - I integrated Dear ImGui in my engine and the text or lines are blurry..
52  - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
53  - How can I help?
54 
55 CODE
56 (search for "[SECTION]" in the code to find them)
57 
58 // [SECTION] FORWARD DECLARATIONS
59 // [SECTION] CONTEXT AND MEMORY ALLOCATORS
60 // [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
61 // [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
62 // [SECTION] MISC HELPER/UTILITIES (ImText* functions)
63 // [SECTION] MISC HELPER/UTILITIES (Color functions)
64 // [SECTION] ImGuiStorage
65 // [SECTION] ImGuiTextFilter
66 // [SECTION] ImGuiTextBuffer
67 // [SECTION] ImGuiListClipper
68 // [SECTION] RENDER HELPERS
69 // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
70 // [SECTION] TOOLTIPS
71 // [SECTION] POPUPS
72 // [SECTION] KEYBOARD/GAMEPAD NAVIGATION
73 // [SECTION] COLUMNS
74 // [SECTION] DRAG AND DROP
75 // [SECTION] LOGGING/CAPTURING
76 // [SECTION] SETTINGS
77 // [SECTION] PLATFORM DEPENDENT HELPERS
78 // [SECTION] METRICS/DEBUG WINDOW
79 
80 */
81 
82 //-----------------------------------------------------------------------------
83 // DOCUMENTATION
84 //-----------------------------------------------------------------------------
85 
86 /*
87 
88  MISSION STATEMENT
89  =================
90 
91  - Easy to use to create code-driven and data-driven tools.
92  - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
93  - Easy to hack and improve.
94  - Minimize screen real-estate usage.
95  - Minimize setup and maintenance.
96  - Minimize state storage on user side.
97  - Portable, minimize dependencies, run on target (consoles, phones, etc.).
98  - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,.
99  opening a tree node for the first time, etc. but a typical frame should not allocate anything).
100 
101  Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
102  - Doesn't look fancy, doesn't animate.
103  - Limited layout features, intricate layouts are typically crafted in code.
104 
105 
106  END-USER GUIDE
107  ==============
108 
109  - Double-click on title bar to collapse window.
110  - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
111  - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
112  - Click and drag on any empty space to move window.
113  - TAB/SHIFT+TAB to cycle through keyboard editable fields.
114  - CTRL+Click on a slider or drag box to input value as text.
115  - Use mouse wheel to scroll.
116  - Text editor:
117  - Hold SHIFT or use mouse to select text.
118  - CTRL+Left/Right to word jump.
119  - CTRL+Shift+Left/Right to select words.
120  - CTRL+A our Double-Click to select all.
121  - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
122  - CTRL+Z,CTRL+Y to undo/redo.
123  - ESCAPE to revert text to its original value.
124  - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
125  - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
126  - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
127  - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW
128 
129 
130  PROGRAMMER GUIDE
131  ================
132 
133  READ FIRST:
134 
135  - Read the FAQ below this section!
136  - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction
137  or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs.
138  - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
139  - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
140  - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
141  You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links docs/README.md.
142  - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances.
143  For every application frame your UI code will be called only once. This is in contrast to e.g. Unity's own implementation of an IMGUI,
144  where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches.
145  - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right.
146  - This codebase is also optimized to yield decent performances with typical "Debug" builds settings.
147  - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected).
148  If you get an assert, read the messages and comments around the assert.
149  - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace.
150  - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
151  See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
152  However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase.
153  - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!).
154 
155  HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI:
156 
157  - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
158  - Or maintain your own branch where you have imconfig.h modified.
159  - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
160  If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
161  from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
162  likely be a comment about it. Please report any issue to the GitHub page!
163  - Try to keep your copy of dear imgui reasonably up to date.
164 
165  GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE:
166 
167  - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
168  - Add the Dear ImGui source files to your projects or using your preferred build system.
169  It is recommended you build and statically link the .cpp files as part of your project and not as shared library (DLL).
170  - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating imgui types with your own maths types.
171  - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
172  - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide.
173  Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
174  phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render().
175  - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
176  - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder.
177 
178  HOW A SIMPLE APPLICATION MAY LOOK LIKE:
179  EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder).
180 
181  // Application init: create a dear imgui context, setup some options, load fonts
182  ImGui::CreateContext();
183  ImGuiIO& io = ImGui::GetIO();
184  // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
185  // TODO: Fill optional fields of the io structure later.
186  // TODO: Load TTF/OTF fonts if you don't want to use the default font.
187 
188  // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11)
189  ImGui_ImplWin32_Init(hwnd);
190  ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
191 
192  // Application main loop
193  while (true)
194  {
195  // Feed inputs to dear imgui, start new frame
196  ImGui_ImplDX11_NewFrame();
197  ImGui_ImplWin32_NewFrame();
198  ImGui::NewFrame();
199 
200  // Any application code here
201  ImGui::Text("Hello, world!");
202 
203  // Render dear imgui into screen
204  ImGui::Render();
205  ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
206  g_pSwapChain->Present(1, 0);
207  }
208 
209  // Shutdown
210  ImGui_ImplDX11_Shutdown();
211  ImGui_ImplWin32_Shutdown();
212  ImGui::DestroyContext();
213 
214  HOW A SIMPLE APPLICATION MAY LOOK LIKE:
215  EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE.
216 
217  // Application init: create a dear imgui context, setup some options, load fonts
218  ImGui::CreateContext();
219  ImGuiIO& io = ImGui::GetIO();
220  // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
221  // TODO: Fill optional fields of the io structure later.
222  // TODO: Load TTF/OTF fonts if you don't want to use the default font.
223 
224  // Build and load the texture atlas into a texture
225  // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
226  int width, height;
227  unsigned char* pixels = NULL;
228  io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
229 
230  // At this point you've got the texture data and you need to upload that your your graphic system:
231  // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
232  // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID.
233  MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
234  io.Fonts->TexID = (void*)texture;
235 
236  // Application main loop
237  while (true)
238  {
239  // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
240  // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings)
241  io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds)
242  io.DisplaySize.x = 1920.0f; // set the current display width
243  io.DisplaySize.y = 1280.0f; // set the current display height here
244  io.MousePos = my_mouse_pos; // set the mouse position
245  io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states
246  io.MouseDown[1] = my_mouse_buttons[1];
247 
248  // Call NewFrame(), after this point you can use ImGui::* functions anytime
249  // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use imgui everywhere)
250  ImGui::NewFrame();
251 
252  // Most of your application code here
253  ImGui::Text("Hello, world!");
254  MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
255  MyGameRender(); // may use any ImGui functions as well!
256 
257  // Render imgui, swap buffers
258  // (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code)
259  ImGui::EndFrame();
260  ImGui::Render();
261  ImDrawData* draw_data = ImGui::GetDrawData();
262  MyImGuiRenderFunction(draw_data);
263  SwapBuffers();
264  }
265 
266  // Shutdown
267  ImGui::DestroyContext();
268 
269  HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE:
270 
271  void void MyImGuiRenderFunction(ImDrawData* draw_data)
272  {
273  // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
274  // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
275  // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
276  // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
277  for (int n = 0; n < draw_data->CmdListsCount; n++)
278  {
279  const ImDrawList* cmd_list = draw_data->CmdLists[n];
280  const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by ImGui
281  const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by ImGui
282  for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
283  {
284  const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
285  if (pcmd->UserCallback)
286  {
287  pcmd->UserCallback(cmd_list, pcmd);
288  }
289  else
290  {
291  // The texture for the draw call is specified by pcmd->TextureId.
292  // The vast majority of draw calls will use the imgui texture atlas, which value you have set yourself during initialization.
293  MyEngineBindTexture((MyTexture*)pcmd->TextureId);
294 
295  // We are using scissoring to clip some objects. All low-level graphics API should supports it.
296  // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
297  // (some elements visible outside their bounds) but you can fix that once everything else works!
298  // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize)
299  // In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize.
300  // However, in the interest of supporting multi-viewport applications in the future (see 'viewport' branch on github),
301  // always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
302  // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
303  ImVec2 pos = draw_data->DisplayPos;
304  MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
305 
306  // Render 'pcmd->ElemCount/3' indexed triangles.
307  // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits in imconfig.h if your engine doesn't support 16-bits indices.
308  MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
309  }
310  idx_buffer += pcmd->ElemCount;
311  }
312  }
313  }
314 
315  - The examples/ folders contains many actual implementation of the pseudo-codes above.
316  - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated.
317  They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs
318  from the rest of your application. In every cases you need to pass on the inputs to imgui. Refer to the FAQ for more information.
319  - Please read the FAQ below!. Amusingly, it is called a FAQ because people frequently run into the same issues!
320 
321  USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
322 
323  - The gamepad/keyboard navigation is fairly functional and keeps being improved.
324  - Gamepad support is particularly useful to use dear imgui on a console system (e.g. PS4, Switch, XB1) without a mouse!
325  - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
326  - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
327  - Gamepad:
328  - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
329  - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
330  Note that io.NavInputs[] is cleared by EndFrame().
331  - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
332  0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
333  - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
334  Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
335  - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://goo.gl/9LgVZW.
336  - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo
337  to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
338  - Keyboard:
339  - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
340  NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
341  - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
342  will be set. For more advanced uses, you may want to read from:
343  - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
344  - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
345  - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
346  Please reach out if you think the game vs navigation input sharing could be improved.
347  - Mouse:
348  - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
349  - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard.
350  - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag.
351  Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
352  When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved.
353  When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that.
354  (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!)
355  (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want
356  to set a boolean to ignore your other external mouse positions until the external source is moved again.)
357 
358 
359  API BREAKING CHANGES
360  ====================
361 
362  Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
363  Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code.
364  When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
365  You can read releases logs https://github.com/ocornut/imgui/releases for more details.
366 
367  - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
368  - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Keep redirection typedef (will obsolete).
369  - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags.
370  - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files.
371  - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
372  - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h.
373  If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths.
374  - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
375  - 2018/08/31 (1.64) - added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp. Re-ordered some of the code remaining in imgui.cpp.
376  NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED.
377  Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions.
378  - 2018/08/22 (1.63) - renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API. Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent).
379  - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete).
380  - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly).
381  - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature.
382  - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency.
383  - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
384  - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
385  - 2018/06/08 (1.62) - examples: the imgui_impl_xxx files have been split to separate platform (Win32, Glfw, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.).
386  old binding will still work as is, however prefer using the separated bindings as they will be updated to be multi-viewport conformant.
387  when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call.
388  - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
389  - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
390  - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more.
391  If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
392  To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code.
393  If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them.
394  - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format",
395  consistent with other functions. Kept redirection functions (will obsolete).
396  - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value.
397  - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch).
398  - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
399  - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically.
400  - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
401  - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment.
402  - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display.
403  - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
404  - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
405  - removed Shutdown() function, as DestroyContext() serve this purpose.
406  - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
407  - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
408  - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
409  - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths.
410  - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
411  - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
412  - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
413  - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side.
414  - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
415  - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags
416  - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame.
417  - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set.
418  - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
419  - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
420  - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
421  - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
422  - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
423  - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed.
424  - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
425  Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions.
426  - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
427  - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
428  - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
429  - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
430  - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency.
431  - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it.
432  - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details.
433  removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
434  - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
435  - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
436  - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Keep redirection typedef (will obsolete).
437  - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
438  - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
439  - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
440  - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
441  - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
442  - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
443  - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
444  - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
445  - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
446  - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
447  - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
448  - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
449  - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
450  - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
451  - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'
452  - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
453  - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
454  - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
455  - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
456  - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
457  - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
458  - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
459  - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
460  If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you.
461  If your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
462  This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color.
463  ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
464  {
465  float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
466  return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);
467  }
468  If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.
469  - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
470  - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
471  - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
472  - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
473  - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
474  - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
475  - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
476  - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
477  - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
478  - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
479  - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
480  - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
481  GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
482  GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!
483  - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
484  - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.
485  - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
486  - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
487  you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
488  - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
489  this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
490  - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
491  - the signature of the io.RenderDrawListsFn handler has changed!
492  old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
493  new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
494  parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
495  ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
496  ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
497  - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
498  - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
499  - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
500  - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
501  - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
502  - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
503  - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
504  - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!
505  - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
506  - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
507  - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
508  - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened.
509  - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
510  - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
511  - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
512  - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
513  - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
514  - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
515  - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
516  - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
517  - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
518  - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
519  - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
520  - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
521  - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
522  - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
523  - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
524  - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
525  - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
526  (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
527  font init: { const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>; }
528  became: { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; }
529  you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
530  it is now recommended that you sample the font texture with bilinear interpolation.
531  (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
532  (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
533  (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
534  - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
535  - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
536  - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
537  - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
538  - 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)
539  - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
540  - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
541  - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
542  - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
543  - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
544  - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
545 
546 
547  FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
548  ======================================
549 
550  Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
551  A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } )
552  - When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application.
553  - When 'io.WantCaptureKeyboard' is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application.
554  - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
555  Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false.
556  This is because imgui needs to detect that you clicked in the void to unfocus its own windows.
557  Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!).
558  It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs.
559  Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also
560  perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to UpdateHoveredWindowAndCaptureFlags().
561  Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically
562  have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
563  were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
564 
565  Q: How can I display an image? What is ImTextureID, how does it works?
566  A: Short explanation:
567  - You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures.
568  - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
569  - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
570  Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.
571 
572  Long explanation:
573  - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices.
574  At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code
575  to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
576  - Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
577  We carry the information to identify a "texture" in the ImTextureID type.
578  ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
579  Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
580  - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying
581  an image from the end-user perspective. This is what the _examples_ rendering functions are using:
582 
583  OpenGL: ImTextureID = GLuint (see ImGui_ImplGlfwGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp)
584  DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp)
585  DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp)
586  DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp)
587 
588  For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
589  Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure
590  tying together both the texture and information about its format and how to read it.
591  - If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about
592  the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase
593  is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
594  If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID
595  representation suggested by the example bindings is probably the best choice.
596  (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
597 
598  User code may do:
599 
600  // Cast our texture type to ImTextureID / void*
601  MyTexture* texture = g_CoffeeTableTexture;
602  ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
603 
604  The renderer function called after ImGui::Render() will receive that same value that the user code passed:
605 
606  // Cast ImTextureID / void* stored in the draw command as our texture type
607  MyTexture* texture = (MyTexture*)pcmd->TextureId;
608  MyEngineBindTexture2D(texture);
609 
610  Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
611  This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
612  If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
613 
614  Here's a simplified OpenGL example using stb_image.h:
615 
616  // Use stb_image.h to load a PNG from disk and turn it into raw RGBA pixel data:
617  #define STB_IMAGE_IMPLEMENTATION
618  #include <stb_image.h>
619  [...]
620  int my_image_width, my_image_height;
621  unsigned char* my_image_data = stbi_load("my_image.png", &my_image_width, &my_image_height, NULL, 4);
622 
623  // Turn the RGBA pixel data into an OpenGL texture:
624  GLuint my_opengl_texture;
625  glGenTextures(1, &my_opengl_texture);
626  glBindTexture(GL_TEXTURE_2D, my_opengl_texture);
627  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
628  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
629  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
630  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
631 
632  // Now that we have an OpenGL texture, assuming our imgui rendering function (imgui_impl_xxx.cpp file) takes GLuint as ImTextureID, we can display it:
633  ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(my_image_width, my_image_height));
634 
635  C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTexture / void*, and vice-versa.
636  Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTexture / void*.
637  Examples:
638 
639  GLuint my_tex = XXX;
640  void* my_void_ptr;
641  my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
642  my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
643 
644  ID3D11ShaderResourceView* my_dx11_srv = XXX;
645  void* my_void_ptr;
646  my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
647  my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
648 
649  Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
650 
651  Q: How can I have multiple widgets with the same label or with an empty label?
652  Q: I have multiple widgets with the same label, and only the first one works. Why is that?
653  A: A primer on labels and the ID Stack...
654 
655  Dear ImGui internally need to uniquely identify UI elements.
656  Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
657  Interactive widgets (such as calls to Button buttons) need a unique ID.
658  Unique ID are used internally to track active widgets and occasionally associate state to widgets.
659  Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
660 
661  - Unique ID are often derived from a string label:
662 
663  Button("OK"); // Label = "OK", ID = hash of (..., "OK")
664  Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel")
665 
666  - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
667  two buttons labeled "OK" in different windows or different tree locations is fine.
668  We used "..." above to signify whatever was already pushed to the ID stack previously:
669 
670  Begin("MyWindow");
671  Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
672  End();
673  Begin("MyOtherWindow");
674  Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
675  End();
676 
677  - If you have a same ID twice in the same location, you'll have a conflict:
678 
679  Button("OK");
680  Button("OK"); // ID collision! Interacting with either button will trigger the first one.
681 
682  Fear not! this is easy to solve and there are many ways to solve it!
683 
684  - Solving ID conflict in a simple/local context:
685  When passing a label you can optionally specify extra ID information within string itself.
686  Use "##" to pass a complement to the ID that won't be visible to the end-user.
687  This helps solving the simple collision cases when you know e.g. at compilation time which items
688  are going to be created:
689 
690  Begin("MyWindow");
691  Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
692  Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above
693  Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above
694  End();
695 
696  - If you want to completely hide the label, but still need an ID:
697 
698  Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
699 
700  - Occasionally/rarely you might want change a label while preserving a constant ID. This allows
701  you to animate labels. For example you may want to include varying information in a window title bar,
702  but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
703 
704  Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "ID")
705  Button("World###ID"); // Label = "World", ID = hash of (..., "ID") // Same as above, even though the label looks different
706 
707  sprintf(buf, "My game (%f FPS)###MyGame", fps);
708  Begin(buf); // Variable title, ID = hash of "MyGame"
709 
710  - Solving ID conflict in a more general manner:
711  Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
712  within the same window. This is the most convenient way of distinguishing ID when iterating and
713  creating many UI elements programmatically.
714  You can push a pointer, a string or an integer value into the ID stack.
715  Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
716  At each level of the stack we store the seed used for items at this level of the ID stack.
717 
718  Begin("Window");
719  for (int i = 0; i < 100; i++)
720  {
721  PushID(i); // Push i to the id tack
722  Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
723  PopID();
724  }
725  for (int i = 0; i < 100; i++)
726  {
727  MyObject* obj = Objects[i];
728  PushID(obj);
729  Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
730  PopID();
731  }
732  for (int i = 0; i < 100; i++)
733  {
734  MyObject* obj = Objects[i];
735  PushID(obj->Name);
736  Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
737  PopID();
738  }
739  End();
740 
741  - You can stack multiple prefixes into the ID stack:
742 
743  Button("Click"); // Label = "Click", ID = hash of (..., "Click")
744  PushID("node");
745  Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
746  PushID(my_ptr);
747  Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click")
748  PopID();
749  PopID();
750 
751  - Tree nodes implicitly creates a scope for you by calling PushID().
752 
753  Button("Click"); // Label = "Click", ID = hash of (..., "Click")
754  if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
755  {
756  Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
757  TreePop();
758  }
759 
760  - When working with trees, ID are used to preserve the open/close state of each tree node.
761  Depending on your use cases you may want to use strings, indices or pointers as ID.
762  e.g. when following a single pointer that may change over time, using a static string as ID
763  will preserve your node open/closed state when the targeted object change.
764  e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
765  node open/closed state differently. See what makes more sense in your situation!
766 
767  Q: How can I use my own math types instead of ImVec2/ImVec4?
768  A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions.
769  This way you'll be able to use your own types everywhere, e.g. passsing glm::vec2 to ImGui functions instead of ImVec2.
770 
771  Q: How can I load a different font than the default?
772  A: Use the font atlas to load the TTF/OTF file you want:
773  ImGuiIO& io = ImGui::GetIO();
774  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
775  io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
776  Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
777  (Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
778  (Read the 'misc/fonts/README.txt' file for more details about font loading.)
779 
780  New programmers: remember that in C/C++ and most programming languages if you want to use a
781  backslash \ within a string literal, you need to write it double backslash "\\":
782  io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!)
783  io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT
784  io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT
785 
786  Q: How can I easily use icons in my application?
787  A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you
788  main font. Then you can refer to icons within your strings.
789  You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment.
790  (Read the 'misc/fonts/README.txt' file for more details about icons font loading.)
791 
792  Q: How can I load multiple fonts?
793  A: Use the font atlas to pack them into a single texture:
794  (Read the 'misc/fonts/README.txt' file and the code in ImFontAtlas for more details.)
795 
796  ImGuiIO& io = ImGui::GetIO();
797  ImFont* font0 = io.Fonts->AddFontDefault();
798  ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
799  ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
800  io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
801  // the first loaded font gets used by default
802  // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
803 
804  // Options
805  ImFontConfig config;
806  config.OversampleH = 3;
807  config.OversampleV = 1;
808  config.GlyphOffset.y -= 2.0f; // Move everything by 2 pixels up
809  config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
810  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
811 
812  // Combine multiple fonts into one (e.g. for icon fonts)
813  static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
814  ImFontConfig config;
815  config.MergeMode = true;
816  io.Fonts->AddFontDefault();
817  io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
818  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
819 
820  Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
821  A: When loading a font, pass custom Unicode ranges to specify the glyphs to load.
822 
823  // Add default Japanese ranges
824  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
825 
826  // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
827  ImVector<ImWchar> ranges;
828  ImFontGlyphRangesBuilder builder;
829  builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
830  builder.AddChar(0x7262); // Add a specific character
831  builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
832  builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
833  io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
834 
835  All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
836  by using the u8"hello" syntax. Specifying literal in your source code using a local code page
837  (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
838  Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
839 
840  Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter().
841  The applications in examples/ are doing that.
842  Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
843  You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
844  Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
845  the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
846 
847  Q: How can I interact with standard C++ types (such as std::string and std::vector)?
848  A: - Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers),
849  and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use
850  any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
851  - To use ImGui::InputText() with a std::string or any resizable string class, see misc/cpp/imgui_stdlib.h.
852  - To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API
853  lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API.
854  Prefer using them over the old and awkward Combo()/ListBox() api.
855  - Generally for most high-level types you should be able to access the underlying data type.
856  You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
857  - Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
858  to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
859  Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances.
860  Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those
861  are not configurable and not the same across implementations.
862  - If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
863  of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
864  is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
865  One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
866  This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
867  provide similar or better string helpers.
868 
869  Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
870  A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags.
871  (The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse)
872  Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
873  - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows.
874  - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create
875  your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data.
876 
877  Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
878  A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
879  (short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad)
880  - You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy)
881  This is the preferred solution for developer productivity.
882  In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple
883  and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
884  to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
885  Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
886  - You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends
887  the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine.
888  - For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate
889  for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
890  for screen real-estate and precision.
891 
892  Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
893  A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
894  Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
895 
896  Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
897  A: You are probably mishandling the clipping rectangles in your render function.
898  Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
899 
900  Q: How can I help?
901  A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt
902  and see how you want to help and can help!
903  - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui.
904  - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README.
905  - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
906  You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers.
907  But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
908  - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately).
909 
910  - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
911  this is also useful to set yourself in the context of another window (to get/set other settings)
912  - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
913  - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle
914  of a deep nested inner loop in your code.
915  - tip: you can call Render() multiple times (e.g for VR renders).
916  - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui!
917 
918 */
919 
920 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
921 #define _CRT_SECURE_NO_WARNINGS
922 #endif
923 
924 #include "imgui.h"
925 #ifndef IMGUI_DEFINE_MATH_OPERATORS
926 #define IMGUI_DEFINE_MATH_OPERATORS
927 #endif
928 #include "imgui_internal.h"
929 
930 #include <ctype.h> // toupper, isprint
931 #include <stdio.h> // vsnprintf, sscanf, printf
932 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
933 #include <stddef.h> // intptr_t
934 #else
935 #include <stdint.h> // intptr_t
936 #endif
937 
938 // Debug options
939 #define IMGUI_DEBUG_NAV_SCORING 0
940 #define IMGUI_DEBUG_NAV_RECTS 0
941 
942 // Visual Studio warnings
943 #ifdef _MSC_VER
944 #pragma warning (disable: 4127) // condition expression is constant
945 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
946 #endif
947 
948 // Clang/GCC warnings with -Weverything
949 #ifdef __clang__
950 #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!
951 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
952 #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
953 #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.
954 #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.
955 #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
956 #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
957 #pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
958 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
959 #elif defined(__GNUC__)
960 #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
961 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
962 #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
963 #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
964 #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
965 #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
966 #pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
967 #if __GNUC__ >= 8
968 #pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
969 #endif
970 #endif
971 
972 // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
973 static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
974 static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
975 
976 // Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end)
977 static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f; // Extend outside and inside windows. Affect FindHoveredWindow().
978 static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
979 
980 //-------------------------------------------------------------------------
981 // [SECTION] FORWARD DECLARATIONS
982 //-------------------------------------------------------------------------
983 
984 static void SetCurrentWindow(ImGuiWindow* window);
985 static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
986 static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
987 static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
988 static void FindHoveredWindow();
989 static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
990 static void CheckStacksSize(ImGuiWindow* window, bool write);
991 static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
992 
993 static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
994 static void AddWindowToDrawData(ImVector<ImDrawList*>* out_list, ImGuiWindow* window);
995 static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
996 
997 static ImRect GetViewportRect();
998 
999 // Settings
1000 static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
1001 static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
1003 
1004 // Platform Dependents default implementation for IO functions
1005 static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
1006 static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
1007 static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
1008 
1009 namespace ImGui
1010 {
1011 static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
1012 
1013 // Navigation
1014 static void NavUpdate();
1015 static void NavUpdateWindowing();
1016 static void NavUpdateWindowingList();
1017 static void NavUpdateMoveResult();
1018 static float NavUpdatePageUpPageDown(int allowed_dir_flags);
1019 static inline void NavUpdateAnyRequestFlag();
1020 static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
1022 static void NavSaveLastChildNavWindow(ImGuiWindow* nav_window);
1024 
1025 // Misc
1026 static void UpdateMouseInputs();
1027 static void UpdateMouseWheel();
1028 static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
1029 }
1030 
1031 //-----------------------------------------------------------------------------
1032 // [SECTION] CONTEXT AND MEMORY ALLOCATORS
1033 //-----------------------------------------------------------------------------
1034 
1035 // Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
1036 // CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
1037 // If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file.
1038 // ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can:
1039 // - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
1040 // - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
1041 #ifndef GImGui
1043 #endif
1044 
1045 // Memory Allocator functions. Use SetAllocatorFunctions() to change them.
1046 // If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
1047 // Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
1048 #ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1049 static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); }
1050 static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); }
1051 #else
1052 static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; (void)size; IM_ASSERT(0); return NULL; }
1053 static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; (void)ptr; IM_ASSERT(0); }
1054 #endif
1055 
1056 static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
1057 static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
1058 static void* GImAllocatorUserData = NULL;
1059 
1060 //-----------------------------------------------------------------------------
1061 // [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
1062 //-----------------------------------------------------------------------------
1063 
1065 {
1066  Alpha = 1.0f; // Global alpha applies to everything in ImGui
1067  WindowPadding = ImVec2(8,8); // Padding within a window
1068  WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
1069  WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1070  WindowMinSize = ImVec2(32,32); // Minimum window size
1071  WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
1072  ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
1073  ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1074  PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
1075  PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1076  FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
1077  FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
1078  FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
1079  ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
1080  ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
1081  TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
1082  IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
1083  ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
1084  ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
1085  ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
1086  GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
1087  GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
1088  TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
1089  TabBorderSize = 0.0f; // Thickness of border around tabs.
1090  ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
1091  DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
1092  DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
1093  MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
1094  AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
1095  AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
1096  CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
1097 
1098  // Default theme
1099  ImGui::StyleColorsDark(this);
1100 }
1101 
1102 // To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you.
1103 // Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
1104 void ImGuiStyle::ScaleAllSizes(float scale_factor)
1105 {
1106  WindowPadding = ImFloor(WindowPadding * scale_factor);
1107  WindowRounding = ImFloor(WindowRounding * scale_factor);
1108  WindowMinSize = ImFloor(WindowMinSize * scale_factor);
1109  ChildRounding = ImFloor(ChildRounding * scale_factor);
1110  PopupRounding = ImFloor(PopupRounding * scale_factor);
1111  FramePadding = ImFloor(FramePadding * scale_factor);
1112  FrameRounding = ImFloor(FrameRounding * scale_factor);
1113  TabRounding = ImFloor(TabRounding * scale_factor);
1114  ItemSpacing = ImFloor(ItemSpacing * scale_factor);
1115  ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
1116  TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
1117  IndentSpacing = ImFloor(IndentSpacing * scale_factor);
1118  ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
1119  ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
1120  ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
1121  GrabMinSize = ImFloor(GrabMinSize * scale_factor);
1122  GrabRounding = ImFloor(GrabRounding * scale_factor);
1123  DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
1124  DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
1125  MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
1126 }
1127 
1129 {
1130  // Most fields are initialized with zero
1131  memset(this, 0, sizeof(*this));
1132 
1133  // Settings
1134  ConfigFlags = ImGuiConfigFlags_None;
1135  BackendFlags = ImGuiBackendFlags_None;
1136  DisplaySize = ImVec2(-1.0f, -1.0f);
1137  DeltaTime = 1.0f/60.0f;
1138  IniSavingRate = 5.0f;
1139  IniFilename = "imgui.ini";
1140  LogFilename = "imgui_log.txt";
1141  MouseDoubleClickTime = 0.30f;
1142  MouseDoubleClickMaxDist = 6.0f;
1143  for (int i = 0; i < ImGuiKey_COUNT; i++)
1144  KeyMap[i] = -1;
1145  KeyRepeatDelay = 0.250f;
1146  KeyRepeatRate = 0.050f;
1147  UserData = NULL;
1148 
1149  Fonts = NULL;
1150  FontGlobalScale = 1.0f;
1151  FontDefault = NULL;
1152  FontAllowUserScaling = false;
1153  DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
1154  DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f);
1155 
1156  // Miscellaneous configuration options
1157 #ifdef __APPLE__
1158  ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag
1159 #else
1160  ConfigMacOSXBehaviors = false;
1161 #endif
1162  ConfigInputTextCursorBlink = true;
1163  ConfigWindowsResizeFromEdges = true;
1164  ConfigWindowsMoveFromTitleBarOnly = false;
1165 
1166  // Platform Functions
1167  BackendPlatformName = BackendRendererName = NULL;
1168  BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
1169  GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
1170  SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
1171  ClipboardUserData = NULL;
1172  ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
1173  ImeWindowHandle = NULL;
1174 
1175 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1176  RenderDrawListsFn = NULL;
1177 #endif
1178 
1179  // Input (NB: we already have memset zero the entire structure!)
1180  MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1181  MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
1182  MouseDragThreshold = 6.0f;
1183  for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
1184  for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
1185  for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
1186 }
1187 
1188 // Pass in translated ASCII characters for text input.
1189 // - with glfw you can get those from the callback set in glfwSetCharCallback()
1190 // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
1192 {
1193  InputQueueCharacters.push_back(c);
1194 }
1195 
1196 void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
1197 {
1198  while (*utf8_chars != 0)
1199  {
1200  unsigned int c = 0;
1201  utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
1202  if (c > 0 && c <= 0xFFFF)
1203  InputQueueCharacters.push_back((ImWchar)c);
1204  }
1205 }
1206 
1208 {
1209  InputQueueCharacters.resize(0);
1210 }
1211 
1212 //-----------------------------------------------------------------------------
1213 // [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
1214 //-----------------------------------------------------------------------------
1215 
1216 ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
1217 {
1218  ImVec2 ap = p - a;
1219  ImVec2 ab_dir = b - a;
1220  float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
1221  if (dot < 0.0f)
1222  return a;
1223  float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
1224  if (dot > ab_len_sqr)
1225  return b;
1226  return a + ab_dir * dot / ab_len_sqr;
1227 }
1228 
1229 bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
1230 {
1231  bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
1232  bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
1233  bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
1234  return ((b1 == b2) && (b2 == b3));
1235 }
1236 
1237 void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
1238 {
1239  ImVec2 v0 = b - a;
1240  ImVec2 v1 = c - a;
1241  ImVec2 v2 = p - a;
1242  const float denom = v0.x * v1.y - v1.x * v0.y;
1243  out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
1244  out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
1245  out_u = 1.0f - out_v - out_w;
1246 }
1247 
1248 ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
1249 {
1250  ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
1251  ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
1252  ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
1253  float dist2_ab = ImLengthSqr(p - proj_ab);
1254  float dist2_bc = ImLengthSqr(p - proj_bc);
1255  float dist2_ca = ImLengthSqr(p - proj_ca);
1256  float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
1257  if (m == dist2_ab)
1258  return proj_ab;
1259  if (m == dist2_bc)
1260  return proj_bc;
1261  return proj_ca;
1262 }
1263 
1264 int ImStricmp(const char* str1, const char* str2)
1265 {
1266  int d;
1267  while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
1268  return d;
1269 }
1270 
1271 int ImStrnicmp(const char* str1, const char* str2, size_t count)
1272 {
1273  int d = 0;
1274  while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
1275  return d;
1276 }
1277 
1278 void ImStrncpy(char* dst, const char* src, size_t count)
1279 {
1280  if (count < 1) return;
1281  strncpy(dst, src, count);
1282  dst[count-1] = 0;
1283 }
1284 
1285 char* ImStrdup(const char* str)
1286 {
1287  size_t len = strlen(str);
1288  void* buf = ImGui::MemAlloc(len + 1);
1289  return (char*)memcpy(buf, (const void*)str, len + 1);
1290 }
1291 
1292 char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
1293 {
1294  size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
1295  size_t src_size = strlen(src) + 1;
1296  if (dst_buf_size < src_size)
1297  {
1298  ImGui::MemFree(dst);
1299  dst = (char*)ImGui::MemAlloc(src_size);
1300  if (p_dst_size)
1301  *p_dst_size = src_size;
1302  }
1303  return (char*)memcpy(dst, (const void*)src, src_size);
1304 }
1305 
1306 const char* ImStrchrRange(const char* str, const char* str_end, char c)
1307 {
1308  const char* p = (const char*)memchr(str, (int)c, str_end - str);
1309  return p;
1310 }
1311 
1312 int ImStrlenW(const ImWchar* str)
1313 {
1314  //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bits
1315  int n = 0;
1316  while (*str++) n++;
1317  return n;
1318 }
1319 
1320 // Find end-of-line. Return pointer will point to either first \n, either str_end.
1321 const char* ImStreolRange(const char* str, const char* str_end)
1322 {
1323  const char* p = (const char*)memchr(str, '\n', str_end - str);
1324  return p ? p : str_end;
1325 }
1326 
1327 const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
1328 {
1329  while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
1330  buf_mid_line--;
1331  return buf_mid_line;
1332 }
1333 
1334 const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
1335 {
1336  if (!needle_end)
1337  needle_end = needle + strlen(needle);
1338 
1339  const char un0 = (char)toupper(*needle);
1340  while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
1341  {
1342  if (toupper(*haystack) == un0)
1343  {
1344  const char* b = needle + 1;
1345  for (const char* a = haystack + 1; b < needle_end; a++, b++)
1346  if (toupper(*a) != toupper(*b))
1347  break;
1348  if (b == needle_end)
1349  return haystack;
1350  }
1351  haystack++;
1352  }
1353  return NULL;
1354 }
1355 
1356 // Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible.
1357 void ImStrTrimBlanks(char* buf)
1358 {
1359  char* p = buf;
1360  while (p[0] == ' ' || p[0] == '\t') // Leading blanks
1361  p++;
1362  char* p_start = p;
1363  while (*p != 0) // Find end of string
1364  p++;
1365  while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks
1366  p--;
1367  if (p_start != buf) // Copy memory if we had leading blanks
1368  memmove(buf, p_start, p - p_start);
1369  buf[p - p_start] = 0; // Zero terminate
1370 }
1371 
1372 // A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
1373 // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm.
1374 // B) When buf==NULL vsnprintf() will return the output size.
1375 #ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
1376 
1377 //#define IMGUI_USE_STB_SPRINTF
1378 #ifdef IMGUI_USE_STB_SPRINTF
1379 #define STB_SPRINTF_IMPLEMENTATION
1380 #include "imstb_sprintf.h"
1381 #endif
1382 
1383 #if defined(_MSC_VER) && !defined(vsnprintf)
1384 #define vsnprintf _vsnprintf
1385 #endif
1386 
1387 int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
1388 {
1389  va_list args;
1390  va_start(args, fmt);
1391 #ifdef IMGUI_USE_STB_SPRINTF
1392  int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
1393 #else
1394  int w = vsnprintf(buf, buf_size, fmt, args);
1395 #endif
1396  va_end(args);
1397  if (buf == NULL)
1398  return w;
1399  if (w == -1 || w >= (int)buf_size)
1400  w = (int)buf_size - 1;
1401  buf[w] = 0;
1402  return w;
1403 }
1404 
1405 int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
1406 {
1407 #ifdef IMGUI_USE_STB_SPRINTF
1408  int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
1409 #else
1410  int w = vsnprintf(buf, buf_size, fmt, args);
1411 #endif
1412  if (buf == NULL)
1413  return w;
1414  if (w == -1 || w >= (int)buf_size)
1415  w = (int)buf_size - 1;
1416  buf[w] = 0;
1417  return w;
1418 }
1419 #endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
1420 
1421 // Pass data_size == 0 for zero-terminated strings, data_size > 0 for non-string data.
1422 // Pay attention that data_size==0 will yield different results than passing strlen(data) because the zero-terminated codepath handles ###.
1423 // This should technically be split into two distinct functions (ImHashData/ImHashStr), perhaps once we remove the silly static variable.
1424 // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
1425 ImU32 ImHash(const void* data, int data_size, ImU32 seed)
1426 {
1427  static ImU32 crc32_lut[256] = { 0 };
1428  if (!crc32_lut[1])
1429  {
1430  const ImU32 polynomial = 0xEDB88320;
1431  for (ImU32 i = 0; i < 256; i++)
1432  {
1433  ImU32 crc = i;
1434  for (ImU32 j = 0; j < 8; j++)
1435  crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
1436  crc32_lut[i] = crc;
1437  }
1438  }
1439 
1440  seed = ~seed;
1441  ImU32 crc = seed;
1442  const unsigned char* current = (const unsigned char*)data;
1443 
1444  if (data_size > 0)
1445  {
1446  // Known size
1447  while (data_size--)
1448  crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
1449  }
1450  else
1451  {
1452  // Zero-terminated string
1453  while (unsigned char c = *current++)
1454  {
1455  // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
1456  // Because this syntax is rarely used we are optimizing for the common case.
1457  // - If we reach ### in the string we discard the hash so far and reset to the seed.
1458  // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
1459  if (c == '#' && current[0] == '#' && current[1] == '#')
1460  crc = seed;
1461  crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
1462  }
1463  }
1464  return ~crc;
1465 }
1466 
1467 FILE* ImFileOpen(const char* filename, const char* mode)
1468 {
1469 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
1470  // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can)
1471  const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
1472  const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
1473  ImVector<ImWchar> buf;
1474  buf.resize(filename_wsize + mode_wsize);
1475  ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
1476  ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
1477  return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
1478 #else
1479  return fopen(filename, mode);
1480 #endif
1481 }
1482 
1483 // Load file content into memory
1484 // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
1485 void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes)
1486 {
1487  IM_ASSERT(filename && file_open_mode);
1488  if (out_file_size)
1489  *out_file_size = 0;
1490 
1491  FILE* f;
1492  if ((f = ImFileOpen(filename, file_open_mode)) == NULL)
1493  return NULL;
1494 
1495  long file_size_signed;
1496  if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
1497  {
1498  fclose(f);
1499  return NULL;
1500  }
1501 
1502  size_t file_size = (size_t)file_size_signed;
1503  void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
1504  if (file_data == NULL)
1505  {
1506  fclose(f);
1507  return NULL;
1508  }
1509  if (fread(file_data, 1, file_size, f) != file_size)
1510  {
1511  fclose(f);
1512  ImGui::MemFree(file_data);
1513  return NULL;
1514  }
1515  if (padding_bytes > 0)
1516  memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
1517 
1518  fclose(f);
1519  if (out_file_size)
1520  *out_file_size = file_size;
1521 
1522  return file_data;
1523 }
1524 
1525 //-----------------------------------------------------------------------------
1526 // [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
1527 //-----------------------------------------------------------------------------
1528 
1529 // Convert UTF-8 to 32-bits character, process single character input.
1530 // Based on stb_from_utf8() from github.com/nothings/stb/
1531 // We handle UTF-8 decoding error by skipping forward.
1532 int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
1533 {
1534  unsigned int c = (unsigned int)-1;
1535  const unsigned char* str = (const unsigned char*)in_text;
1536  if (!(*str & 0x80))
1537  {
1538  c = (unsigned int)(*str++);
1539  *out_char = c;
1540  return 1;
1541  }
1542  if ((*str & 0xe0) == 0xc0)
1543  {
1544  *out_char = 0xFFFD; // will be invalid but not end of string
1545  if (in_text_end && in_text_end - (const char*)str < 2) return 1;
1546  if (*str < 0xc2) return 2;
1547  c = (unsigned int)((*str++ & 0x1f) << 6);
1548  if ((*str & 0xc0) != 0x80) return 2;
1549  c += (*str++ & 0x3f);
1550  *out_char = c;
1551  return 2;
1552  }
1553  if ((*str & 0xf0) == 0xe0)
1554  {
1555  *out_char = 0xFFFD; // will be invalid but not end of string
1556  if (in_text_end && in_text_end - (const char*)str < 3) return 1;
1557  if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
1558  if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
1559  c = (unsigned int)((*str++ & 0x0f) << 12);
1560  if ((*str & 0xc0) != 0x80) return 3;
1561  c += (unsigned int)((*str++ & 0x3f) << 6);
1562  if ((*str & 0xc0) != 0x80) return 3;
1563  c += (*str++ & 0x3f);
1564  *out_char = c;
1565  return 3;
1566  }
1567  if ((*str & 0xf8) == 0xf0)
1568  {
1569  *out_char = 0xFFFD; // will be invalid but not end of string
1570  if (in_text_end && in_text_end - (const char*)str < 4) return 1;
1571  if (*str > 0xf4) return 4;
1572  if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
1573  if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
1574  c = (unsigned int)((*str++ & 0x07) << 18);
1575  if ((*str & 0xc0) != 0x80) return 4;
1576  c += (unsigned int)((*str++ & 0x3f) << 12);
1577  if ((*str & 0xc0) != 0x80) return 4;
1578  c += (unsigned int)((*str++ & 0x3f) << 6);
1579  if ((*str & 0xc0) != 0x80) return 4;
1580  c += (*str++ & 0x3f);
1581  // utf-8 encodings of values used in surrogate pairs are invalid
1582  if ((c & 0xFFFFF800) == 0xD800) return 4;
1583  *out_char = c;
1584  return 4;
1585  }
1586  *out_char = 0;
1587  return 0;
1588 }
1589 
1590 int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
1591 {
1592  ImWchar* buf_out = buf;
1593  ImWchar* buf_end = buf + buf_size;
1594  while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
1595  {
1596  unsigned int c;
1597  in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
1598  if (c == 0)
1599  break;
1600  if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes
1601  *buf_out++ = (ImWchar)c;
1602  }
1603  *buf_out = 0;
1604  if (in_text_remaining)
1605  *in_text_remaining = in_text;
1606  return (int)(buf_out - buf);
1607 }
1608 
1609 int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
1610 {
1611  int char_count = 0;
1612  while ((!in_text_end || in_text < in_text_end) && *in_text)
1613  {
1614  unsigned int c;
1615  in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
1616  if (c == 0)
1617  break;
1618  if (c < 0x10000)
1619  char_count++;
1620  }
1621  return char_count;
1622 }
1623 
1624 // Based on stb_to_utf8() from github.com/nothings/stb/
1625 static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
1626 {
1627  if (c < 0x80)
1628  {
1629  buf[0] = (char)c;
1630  return 1;
1631  }
1632  if (c < 0x800)
1633  {
1634  if (buf_size < 2) return 0;
1635  buf[0] = (char)(0xc0 + (c >> 6));
1636  buf[1] = (char)(0x80 + (c & 0x3f));
1637  return 2;
1638  }
1639  if (c >= 0xdc00 && c < 0xe000)
1640  {
1641  return 0;
1642  }
1643  if (c >= 0xd800 && c < 0xdc00)
1644  {
1645  if (buf_size < 4) return 0;
1646  buf[0] = (char)(0xf0 + (c >> 18));
1647  buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
1648  buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
1649  buf[3] = (char)(0x80 + ((c ) & 0x3f));
1650  return 4;
1651  }
1652  //else if (c < 0x10000)
1653  {
1654  if (buf_size < 3) return 0;
1655  buf[0] = (char)(0xe0 + (c >> 12));
1656  buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
1657  buf[2] = (char)(0x80 + ((c ) & 0x3f));
1658  return 3;
1659  }
1660 }
1661 
1662 // Not optimal but we very rarely use this function.
1663 int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
1664 {
1665  unsigned int dummy = 0;
1666  return ImTextCharFromUtf8(&dummy, in_text, in_text_end);
1667 }
1668 
1669 static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
1670 {
1671  if (c < 0x80) return 1;
1672  if (c < 0x800) return 2;
1673  if (c >= 0xdc00 && c < 0xe000) return 0;
1674  if (c >= 0xd800 && c < 0xdc00) return 4;
1675  return 3;
1676 }
1677 
1678 int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
1679 {
1680  char* buf_out = buf;
1681  const char* buf_end = buf + buf_size;
1682  while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
1683  {
1684  unsigned int c = (unsigned int)(*in_text++);
1685  if (c < 0x80)
1686  *buf_out++ = (char)c;
1687  else
1688  buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);
1689  }
1690  *buf_out = 0;
1691  return (int)(buf_out - buf);
1692 }
1693 
1694 int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
1695 {
1696  int bytes_count = 0;
1697  while ((!in_text_end || in_text < in_text_end) && *in_text)
1698  {
1699  unsigned int c = (unsigned int)(*in_text++);
1700  if (c < 0x80)
1701  bytes_count++;
1702  else
1703  bytes_count += ImTextCountUtf8BytesFromChar(c);
1704  }
1705  return bytes_count;
1706 }
1707 
1708 //-----------------------------------------------------------------------------
1709 // [SECTION] MISC HELPER/UTILTIES (Color functions)
1710 // Note: The Convert functions are early design which are not consistent with other API.
1711 //-----------------------------------------------------------------------------
1712 
1714 {
1715  float s = 1.0f/255.0f;
1716  return ImVec4(
1717  ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
1718  ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
1719  ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
1720  ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
1721 }
1722 
1724 {
1725  ImU32 out;
1726  out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
1727  out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
1728  out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
1729  out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
1730  return out;
1731 }
1732 
1733 // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
1734 // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
1735 void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
1736 {
1737  float K = 0.f;
1738  if (g < b)
1739  {
1740  ImSwap(g, b);
1741  K = -1.f;
1742  }
1743  if (r < g)
1744  {
1745  ImSwap(r, g);
1746  K = -2.f / 6.f - K;
1747  }
1748 
1749  const float chroma = r - (g < b ? g : b);
1750  out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
1751  out_s = chroma / (r + 1e-20f);
1752  out_v = r;
1753 }
1754 
1755 // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
1756 // also http://en.wikipedia.org/wiki/HSL_and_HSV
1757 void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
1758 {
1759  if (s == 0.0f)
1760  {
1761  // gray
1762  out_r = out_g = out_b = v;
1763  return;
1764  }
1765 
1766  h = ImFmod(h, 1.0f) / (60.0f/360.0f);
1767  int i = (int)h;
1768  float f = h - (float)i;
1769  float p = v * (1.0f - s);
1770  float q = v * (1.0f - s * f);
1771  float t = v * (1.0f - s * (1.0f - f));
1772 
1773  switch (i)
1774  {
1775  case 0: out_r = v; out_g = t; out_b = p; break;
1776  case 1: out_r = q; out_g = v; out_b = p; break;
1777  case 2: out_r = p; out_g = v; out_b = t; break;
1778  case 3: out_r = p; out_g = q; out_b = v; break;
1779  case 4: out_r = t; out_g = p; out_b = v; break;
1780  case 5: default: out_r = v; out_g = p; out_b = q; break;
1781  }
1782 }
1783 
1784 ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
1785 {
1786  ImGuiStyle& style = GImGui->Style;
1787  ImVec4 c = style.Colors[idx];
1788  c.w *= style.Alpha * alpha_mul;
1789  return ColorConvertFloat4ToU32(c);
1790 }
1791 
1793 {
1794  ImGuiStyle& style = GImGui->Style;
1795  ImVec4 c = col;
1796  c.w *= style.Alpha;
1797  return ColorConvertFloat4ToU32(c);
1798 }
1799 
1801 {
1802  ImGuiStyle& style = GImGui->Style;
1803  return style.Colors[idx];
1804 }
1805 
1807 {
1808  float style_alpha = GImGui->Style.Alpha;
1809  if (style_alpha >= 1.0f)
1810  return col;
1811  ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
1812  a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
1813  return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
1814 }
1815 
1816 //-----------------------------------------------------------------------------
1817 // [SECTION] ImGuiStorage
1818 // Helper: Key->value storage
1819 //-----------------------------------------------------------------------------
1820 
1821 // std::lower_bound but without the bullshit
1823 {
1824  ImGuiStorage::Pair* first = data.Data;
1825  ImGuiStorage::Pair* last = data.Data + data.Size;
1826  size_t count = (size_t)(last - first);
1827  while (count > 0)
1828  {
1829  size_t count2 = count >> 1;
1830  ImGuiStorage::Pair* mid = first + count2;
1831  if (mid->key < key)
1832  {
1833  first = ++mid;
1834  count -= count2 + 1;
1835  }
1836  else
1837  {
1838  count = count2;
1839  }
1840  }
1841  return first;
1842 }
1843 
1844 // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
1846 {
1847  struct StaticFunc
1848  {
1849  static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
1850  {
1851  // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
1852  if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1;
1853  if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1;
1854  return 0;
1855  }
1856  };
1857  if (Data.Size > 1)
1858  ImQsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID);
1859 }
1860 
1861 int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
1862 {
1863  ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1864  if (it == Data.end() || it->key != key)
1865  return default_val;
1866  return it->val_i;
1867 }
1868 
1869 bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
1870 {
1871  return GetInt(key, default_val ? 1 : 0) != 0;
1872 }
1873 
1874 float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
1875 {
1876  ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1877  if (it == Data.end() || it->key != key)
1878  return default_val;
1879  return it->val_f;
1880 }
1881 
1883 {
1884  ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1885  if (it == Data.end() || it->key != key)
1886  return NULL;
1887  return it->val_p;
1888 }
1889 
1890 // 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.
1891 int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
1892 {
1893  ImGuiStorage::Pair* it = LowerBound(Data, key);
1894  if (it == Data.end() || it->key != key)
1895  it = Data.insert(it, Pair(key, default_val));
1896  return &it->val_i;
1897 }
1898 
1899 bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
1900 {
1901  return (bool*)GetIntRef(key, default_val ? 1 : 0);
1902 }
1903 
1904 float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
1905 {
1906  ImGuiStorage::Pair* it = LowerBound(Data, key);
1907  if (it == Data.end() || it->key != key)
1908  it = Data.insert(it, Pair(key, default_val));
1909  return &it->val_f;
1910 }
1911 
1912 void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
1913 {
1914  ImGuiStorage::Pair* it = LowerBound(Data, key);
1915  if (it == Data.end() || it->key != key)
1916  it = Data.insert(it, Pair(key, default_val));
1917  return &it->val_p;
1918 }
1919 
1920 // FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
1921 void ImGuiStorage::SetInt(ImGuiID key, int val)
1922 {
1923  ImGuiStorage::Pair* it = LowerBound(Data, key);
1924  if (it == Data.end() || it->key != key)
1925  {
1926  Data.insert(it, Pair(key, val));
1927  return;
1928  }
1929  it->val_i = val;
1930 }
1931 
1932 void ImGuiStorage::SetBool(ImGuiID key, bool val)
1933 {
1934  SetInt(key, val ? 1 : 0);
1935 }
1936 
1937 void ImGuiStorage::SetFloat(ImGuiID key, float val)
1938 {
1939  ImGuiStorage::Pair* it = LowerBound(Data, key);
1940  if (it == Data.end() || it->key != key)
1941  {
1942  Data.insert(it, Pair(key, val));
1943  return;
1944  }
1945  it->val_f = val;
1946 }
1947 
1948 void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
1949 {
1950  ImGuiStorage::Pair* it = LowerBound(Data, key);
1951  if (it == Data.end() || it->key != key)
1952  {
1953  Data.insert(it, Pair(key, val));
1954  return;
1955  }
1956  it->val_p = val;
1957 }
1958 
1960 {
1961  for (int i = 0; i < Data.Size; i++)
1962  Data[i].val_i = v;
1963 }
1964 
1965 //-----------------------------------------------------------------------------
1966 // [SECTION] ImGuiTextFilter
1967 //-----------------------------------------------------------------------------
1968 
1969 // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
1970 ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
1971 {
1972  if (default_filter)
1973  {
1974  ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
1975  Build();
1976  }
1977  else
1978  {
1979  InputBuf[0] = 0;
1980  CountGrep = 0;
1981  }
1982 }
1983 
1984 bool ImGuiTextFilter::Draw(const char* label, float width)
1985 {
1986  if (width != 0.0f)
1987  ImGui::PushItemWidth(width);
1988  bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
1989  if (width != 0.0f)
1991  if (value_changed)
1992  Build();
1993  return value_changed;
1994 }
1995 
1997 {
1998  out->resize(0);
1999  const char* wb = b;
2000  const char* we = wb;
2001  while (we < e)
2002  {
2003  if (*we == separator)
2004  {
2005  out->push_back(TextRange(wb, we));
2006  wb = we + 1;
2007  }
2008  we++;
2009  }
2010  if (wb != we)
2011  out->push_back(TextRange(wb, we));
2012 }
2013 
2015 {
2016  Filters.resize(0);
2017  TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
2018  input_range.split(',', &Filters);
2019 
2020  CountGrep = 0;
2021  for (int i = 0; i != Filters.Size; i++)
2022  {
2023  TextRange& f = Filters[i];
2024  while (f.b < f.e && ImCharIsBlankA(f.b[0]))
2025  f.b++;
2026  while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
2027  f.e--;
2028  if (f.empty())
2029  continue;
2030  if (Filters[i].b[0] != '-')
2031  CountGrep += 1;
2032  }
2033 }
2034 
2035 bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
2036 {
2037  if (Filters.empty())
2038  return true;
2039 
2040  if (text == NULL)
2041  text = "";
2042 
2043  for (int i = 0; i != Filters.Size; i++)
2044  {
2045  const TextRange& f = Filters[i];
2046  if (f.empty())
2047  continue;
2048  if (f.b[0] == '-')
2049  {
2050  // Subtract
2051  if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)
2052  return false;
2053  }
2054  else
2055  {
2056  // Grep
2057  if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
2058  return true;
2059  }
2060  }
2061 
2062  // Implicit * grep
2063  if (CountGrep == 0)
2064  return true;
2065 
2066  return false;
2067 }
2068 
2069 //-----------------------------------------------------------------------------
2070 // [SECTION] ImGuiTextBuffer
2071 //-----------------------------------------------------------------------------
2072 
2073 // On some platform vsnprintf() takes va_list by reference and modifies it.
2074 // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
2075 #ifndef va_copy
2076 #if defined(__GNUC__) || defined(__clang__)
2077 #define va_copy(dest, src) __builtin_va_copy(dest, src)
2078 #else
2079 #define va_copy(dest, src) (dest = src)
2080 #endif
2081 #endif
2082 
2083 char ImGuiTextBuffer::EmptyString[1] = { 0 };
2084 
2085 // Helper: Text buffer for logging/accumulating text
2086 void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
2087 {
2088  va_list args_copy;
2089  va_copy(args_copy, args);
2090 
2091  int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
2092  if (len <= 0)
2093  {
2094  va_end(args_copy);
2095  return;
2096  }
2097 
2098  // Add zero-terminator the first time
2099  const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2100  const int needed_sz = write_off + len;
2101  if (write_off + len >= Buf.Capacity)
2102  {
2103  int double_capacity = Buf.Capacity * 2;
2104  Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);
2105  }
2106 
2107  Buf.resize(needed_sz);
2108  ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
2109  va_end(args_copy);
2110 }
2111 
2112 void ImGuiTextBuffer::appendf(const char* fmt, ...)
2113 {
2114  va_list args;
2115  va_start(args, fmt);
2116  appendfv(fmt, args);
2117  va_end(args);
2118 }
2119 
2120 //-----------------------------------------------------------------------------
2121 // [SECTION] ImGuiListClipper
2122 // This is currently not as flexible/powerful as it should be, needs some rework (see TODO)
2123 //-----------------------------------------------------------------------------
2124 
2125 static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
2126 {
2127  // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
2128  // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
2129  // The clipper should probably have a 4th step to display the last item in a regular manner.
2130  ImGui::SetCursorPosY(pos_y);
2132  window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
2133  window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
2134  if (window->DC.ColumnsSet)
2135  window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
2136 }
2137 
2138 // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
2139 // Use case B: Begin() called from constructor with items_height>0
2140 // FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.
2141 void ImGuiListClipper::Begin(int count, float items_height)
2142 {
2143  StartPosY = ImGui::GetCursorPosY();
2144  ItemsHeight = items_height;
2145  ItemsCount = count;
2146  StepNo = 0;
2147  DisplayEnd = DisplayStart = -1;
2148  if (ItemsHeight > 0.0f)
2149  {
2150  ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display
2151  if (DisplayStart > 0)
2152  SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor
2153  StepNo = 2;
2154  }
2155 }
2156 
2158 {
2159  if (ItemsCount < 0)
2160  return;
2161  // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user.
2162  if (ItemsCount < INT_MAX)
2163  SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
2164  ItemsCount = -1;
2165  StepNo = 3;
2166 }
2167 
2169 {
2170  if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
2171  {
2172  ItemsCount = -1;
2173  return false;
2174  }
2175  if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height.
2176  {
2177  DisplayStart = 0;
2178  DisplayEnd = 1;
2179  StartPosY = ImGui::GetCursorPosY();
2180  StepNo = 1;
2181  return true;
2182  }
2183  if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
2184  {
2185  if (ItemsCount == 1) { ItemsCount = -1; return false; }
2186  float items_height = ImGui::GetCursorPosY() - StartPosY;
2187  IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically
2188  Begin(ItemsCount-1, items_height);
2189  DisplayStart++;
2190  DisplayEnd++;
2191  StepNo = 3;
2192  return true;
2193  }
2194  if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3.
2195  {
2196  IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);
2197  StepNo = 3;
2198  return true;
2199  }
2200  if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
2201  End();
2202  return false;
2203 }
2204 
2205 //-----------------------------------------------------------------------------
2206 // [SECTION] RENDER HELPERS
2207 // Those (internal) functions are currently quite a legacy mess - their signature and behavior will change.
2208 // Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state.
2209 //-----------------------------------------------------------------------------
2210 
2211 const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
2212 {
2213  const char* text_display_end = text;
2214  if (!text_end)
2215  text_end = (const char*)-1;
2216 
2217  while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
2218  text_display_end++;
2219  return text_display_end;
2220 }
2221 
2222 // Internal ImGui functions to render text
2223 // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
2224 void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
2225 {
2226  ImGuiContext& g = *GImGui;
2227  ImGuiWindow* window = g.CurrentWindow;
2228 
2229  // Hide anything after a '##' string
2230  const char* text_display_end;
2231  if (hide_text_after_hash)
2232  {
2233  text_display_end = FindRenderedTextEnd(text, text_end);
2234  }
2235  else
2236  {
2237  if (!text_end)
2238  text_end = text + strlen(text); // FIXME-OPT
2239  text_display_end = text_end;
2240  }
2241 
2242  if (text != text_display_end)
2243  {
2244  window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
2245  if (g.LogEnabled)
2246  LogRenderedText(&pos, text, text_display_end);
2247  }
2248 }
2249 
2250 void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
2251 {
2252  ImGuiContext& g = *GImGui;
2253  ImGuiWindow* window = g.CurrentWindow;
2254 
2255  if (!text_end)
2256  text_end = text + strlen(text); // FIXME-OPT
2257 
2258  if (text != text_end)
2259  {
2260  window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
2261  if (g.LogEnabled)
2262  LogRenderedText(&pos, text, text_end);
2263  }
2264 }
2265 
2266 // Default clip_rect uses (pos_min,pos_max)
2267 // Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
2268 void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
2269 {
2270  // Perform CPU side clipping for single clipped element to avoid using scissor state
2271  ImVec2 pos = pos_min;
2272  const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
2273 
2274  const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
2275  const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
2276  bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
2277  if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
2278  need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
2279 
2280  // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
2281  if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
2282  if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
2283 
2284  // Render
2285  if (need_clipping)
2286  {
2287  ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
2288  draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
2289  }
2290  else
2291  {
2292  draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
2293  }
2294 }
2295 
2296 void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
2297 {
2298  // Hide anything after a '##' string
2299  const char* text_display_end = FindRenderedTextEnd(text, text_end);
2300  const int text_len = (int)(text_display_end - text);
2301  if (text_len == 0)
2302  return;
2303 
2304  ImGuiContext& g = *GImGui;
2305  ImGuiWindow* window = g.CurrentWindow;
2306  RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
2307  if (g.LogEnabled)
2308  LogRenderedText(&pos_min, text, text_display_end);
2309 }
2310 
2311 // Render a rectangle shaped with optional rounding and borders
2312 void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
2313 {
2314  ImGuiContext& g = *GImGui;
2315  ImGuiWindow* window = g.CurrentWindow;
2316  window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
2317  const float border_size = g.Style.FrameBorderSize;
2318  if (border && border_size > 0.0f)
2319  {
2320  window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2321  window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2322  }
2323 }
2324 
2325 void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
2326 {
2327  ImGuiContext& g = *GImGui;
2328  ImGuiWindow* window = g.CurrentWindow;
2329  const float border_size = g.Style.FrameBorderSize;
2330  if (border_size > 0.0f)
2331  {
2332  window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2333  window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2334  }
2335 }
2336 
2337 // Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
2338 void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale)
2339 {
2340  ImGuiContext& g = *GImGui;
2341 
2342  const float h = g.FontSize * 1.00f;
2343  float r = h * 0.40f * scale;
2344  ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale);
2345 
2346  ImVec2 a, b, c;
2347  switch (dir)
2348  {
2349  case ImGuiDir_Up:
2350  case ImGuiDir_Down:
2351  if (dir == ImGuiDir_Up) r = -r;
2352  a = ImVec2(+0.000f,+0.750f) * r;
2353  b = ImVec2(-0.866f,-0.750f) * r;
2354  c = ImVec2(+0.866f,-0.750f) * r;
2355  break;
2356  case ImGuiDir_Left:
2357  case ImGuiDir_Right:
2358  if (dir == ImGuiDir_Left) r = -r;
2359  a = ImVec2(+0.750f,+0.000f) * r;
2360  b = ImVec2(-0.750f,+0.866f) * r;
2361  c = ImVec2(-0.750f,-0.866f) * r;
2362  break;
2363  case ImGuiDir_None:
2364  case ImGuiDir_COUNT:
2365  IM_ASSERT(0);
2366  break;
2367  }
2368 
2369  g.CurrentWindow->DrawList->AddTriangleFilled(center + a, center + b, center + c, GetColorU32(ImGuiCol_Text));
2370 }
2371 
2373 {
2374  ImGuiContext& g = *GImGui;
2375  ImGuiWindow* window = g.CurrentWindow;
2376  window->DrawList->AddCircleFilled(pos, g.FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
2377 }
2378 
2379 void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz)
2380 {
2381  ImGuiContext& g = *GImGui;
2382  ImGuiWindow* window = g.CurrentWindow;
2383 
2384  float thickness = ImMax(sz / 5.0f, 1.0f);
2385  sz -= thickness*0.5f;
2386  pos += ImVec2(thickness*0.25f, thickness*0.25f);
2387 
2388  float third = sz / 3.0f;
2389  float bx = pos.x + third;
2390  float by = pos.y + sz - third*0.5f;
2391  window->DrawList->PathLineTo(ImVec2(bx - third, by - third));
2392  window->DrawList->PathLineTo(ImVec2(bx, by));
2393  window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2));
2394  window->DrawList->PathStroke(col, false, thickness);
2395 }
2396 
2398 {
2399  ImGuiContext& g = *GImGui;
2400  if (id != g.NavId)
2401  return;
2403  return;
2404  ImGuiWindow* window = g.CurrentWindow;
2405  if (window->DC.NavHideHighlightOneFrame)
2406  return;
2407 
2408  float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
2409  ImRect display_rect = bb;
2410  display_rect.ClipWith(window->ClipRect);
2412  {
2413  const float THICKNESS = 2.0f;
2414  const float DISTANCE = 3.0f + THICKNESS * 0.5f;
2415  display_rect.Expand(ImVec2(DISTANCE,DISTANCE));
2416  bool fully_visible = window->ClipRect.Contains(display_rect);
2417  if (!fully_visible)
2418  window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
2419  window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
2420  if (!fully_visible)
2421  window->DrawList->PopClipRect();
2422  }
2423  if (flags & ImGuiNavHighlightFlags_TypeThin)
2424  {
2425  window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
2426  }
2427 }
2428 
2429 //-----------------------------------------------------------------------------
2430 // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
2431 //-----------------------------------------------------------------------------
2432 
2433 // ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
2434 ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
2435  : DrawListInst(&context->DrawListSharedData)
2436 {
2437  Name = ImStrdup(name);
2438  ID = ImHash(name, 0);
2439  IDStack.push_back(ID);
2441  Pos = ImVec2(0.0f, 0.0f);
2442  Size = SizeFull = ImVec2(0.0f, 0.0f);
2444  WindowPadding = ImVec2(0.0f, 0.0f);
2445  WindowRounding = 0.0f;
2446  WindowBorderSize = 0.0f;
2447  NameBufLen = (int)strlen(name) + 1;
2448  MoveId = GetID("#MOVE");
2449  ChildId = 0;
2450  Scroll = ImVec2(0.0f, 0.0f);
2451  ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
2452  ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
2453  ScrollbarSizes = ImVec2(0.0f, 0.0f);
2454  ScrollbarX = ScrollbarY = false;
2455  Active = WasActive = false;
2456  WriteAccessed = false;
2457  Collapsed = false;
2458  WantCollapseToggle = false;
2459  SkipItems = false;
2460  Appearing = false;
2461  Hidden = false;
2462  HasCloseButton = false;
2463  BeginCount = 0;
2466  PopupId = 0;
2468  AutoFitOnlyGrows = false;
2469  AutoFitChildAxises = 0x00;
2473  SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
2474 
2475  LastFrameActive = -1;
2476  ItemWidthDefault = 0.0f;
2477  FontWindowScale = 1.0f;
2478  SettingsIdx = -1;
2479 
2482  ParentWindow = NULL;
2483  RootWindow = NULL;
2485  RootWindowForNav = NULL;
2486 
2487  NavLastIds[0] = NavLastIds[1] = 0;
2488  NavRectRel[0] = NavRectRel[1] = ImRect();
2489  NavLastChildNavWindow = NULL;
2490 
2494 }
2495 
2497 {
2499  IM_DELETE(Name);
2500  for (int i = 0; i != ColumnsStorage.Size; i++)
2502 }
2503 
2504 ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
2505 {
2506  ImGuiID seed = IDStack.back();
2507  ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
2508  ImGui::KeepAliveID(id);
2509  return id;
2510 }
2511 
2512 ImGuiID ImGuiWindow::GetID(const void* ptr)
2513 {
2514  ImGuiID seed = IDStack.back();
2515  ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
2516  ImGui::KeepAliveID(id);
2517  return id;
2518 }
2519 
2520 ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
2521 {
2522  ImGuiID seed = IDStack.back();
2523  return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
2524 }
2525 
2527 {
2528  ImGuiID seed = IDStack.back();
2529  return ImHash(&ptr, sizeof(void*), seed);
2530 }
2531 
2532 // This is only used in rare/specific situations to manufacture an ID out of nowhere.
2534 {
2535  ImGuiID seed = IDStack.back();
2536  const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) };
2537  ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed);
2538  ImGui::KeepAliveID(id);
2539  return id;
2540 }
2541 
2542 static void SetCurrentWindow(ImGuiWindow* window)
2543 {
2544  ImGuiContext& g = *GImGui;
2545  g.CurrentWindow = window;
2546  if (window)
2548 }
2549 
2550 void ImGui::SetNavID(ImGuiID id, int nav_layer)
2551 {
2552  ImGuiContext& g = *GImGui;
2553  IM_ASSERT(g.NavWindow);
2554  IM_ASSERT(nav_layer == 0 || nav_layer == 1);
2555  g.NavId = id;
2556  g.NavWindow->NavLastIds[nav_layer] = id;
2557 }
2558 
2559 void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel)
2560 {
2561  ImGuiContext& g = *GImGui;
2562  SetNavID(id, nav_layer);
2563  g.NavWindow->NavRectRel[nav_layer] = rect_rel;
2564  g.NavMousePosDirty = true;
2565  g.NavDisableHighlight = false;
2566  g.NavDisableMouseHover = true;
2567 }
2568 
2570 {
2571  ImGuiContext& g = *GImGui;
2572  g.ActiveIdIsJustActivated = (g.ActiveId != id);
2574  {
2575  g.ActiveIdTimer = 0.0f;
2576  g.ActiveIdHasBeenEdited = false;
2577  if (id != 0)
2578  {
2579  g.LastActiveId = id;
2580  g.LastActiveIdTimer = 0.0f;
2581  }
2582  }
2583  g.ActiveId = id;
2585  g.ActiveIdAllowOverlap = false;
2586  g.ActiveIdWindow = window;
2587  if (id)
2588  {
2589  g.ActiveIdIsAlive = id;
2591  }
2592 }
2593 
2594 // FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring.
2596 {
2597  ImGuiContext& g = *GImGui;
2598  IM_ASSERT(id != 0);
2599 
2600  // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it.
2601  const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
2602  if (g.NavWindow != window)
2603  g.NavInitRequest = false;
2604  g.NavId = id;
2605  g.NavWindow = window;
2606  g.NavLayer = nav_layer;
2607  window->NavLastIds[nav_layer] = id;
2608  if (window->DC.LastItemId == id)
2609  window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
2610 
2612  g.NavDisableMouseHover = true;
2613  else
2614  g.NavDisableHighlight = true;
2615 }
2616 
2618 {
2619  SetActiveID(0, NULL);
2620 }
2621 
2623 {
2624  ImGuiContext& g = *GImGui;
2625  g.HoveredId = id;
2626  g.HoveredIdAllowOverlap = false;
2627  if (id != 0 && g.HoveredIdPreviousFrame != id)
2629 }
2630 
2632 {
2633  ImGuiContext& g = *GImGui;
2634  return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
2635 }
2636 
2638 {
2639  ImGuiContext& g = *GImGui;
2640  if (g.ActiveId == id)
2641  g.ActiveIdIsAlive = id;
2642  if (g.ActiveIdPreviousFrame == id)
2644 }
2645 
2647 {
2648  // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
2649  // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data.
2650  (void)id; // Avoid unused variable warnings when asserts are compiled out.
2651  ImGuiContext& g = *GImGui;
2652  IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
2653  //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
2654  g.ActiveIdHasBeenEdited = true;
2656 }
2657 
2658 static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
2659 {
2660  // An active popup disable hovering on other windows (apart from its own children)
2661  // FIXME-OPT: This could be cached/stored within the window.
2662  ImGuiContext& g = *GImGui;
2663  if (g.NavWindow)
2664  if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
2665  if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
2666  {
2667  // For the purpose of those flags we differentiate "standard popup" from "modal popup"
2668  // NB: The order of those two tests is important because Modal windows are also Popups.
2669  if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
2670  return false;
2671  if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
2672  return false;
2673  }
2674 
2675  return true;
2676 }
2677 
2678 // Advance cursor given item size for layout.
2679 void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
2680 {
2681  ImGuiContext& g = *GImGui;
2682  ImGuiWindow* window = g.CurrentWindow;
2683  if (window->SkipItems)
2684  return;
2685 
2686  // Always align ourselves on pixel boundaries
2687  const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
2688  const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
2689  //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
2690  window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
2691  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
2692  window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
2693  window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
2694  window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
2695  //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
2696 
2697  window->DC.PrevLineSize.y = line_height;
2698  window->DC.PrevLineTextBaseOffset = text_base_offset;
2699  window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
2700 
2701  // Horizontal layout mode
2702  if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
2703  SameLine();
2704 }
2705 
2706 void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
2707 {
2708  ItemSize(bb.GetSize(), text_offset_y);
2709 }
2710 
2711 // Declare item bounding box for clipping and interaction.
2712 // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
2713 // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
2714 bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
2715 {
2716  ImGuiContext& g = *GImGui;
2717  ImGuiWindow* window = g.CurrentWindow;
2718 
2719  if (id != 0)
2720  {
2721  // Navigation processing runs prior to clipping early-out
2722  // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
2723  // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window.
2724  // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
2725  // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick)
2726  window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask;
2727  if (g.NavId == id || g.NavAnyRequest)
2728  if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
2729  if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
2730  NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id);
2731  }
2732 
2733  window->DC.LastItemId = id;
2734  window->DC.LastItemRect = bb;
2736 
2737 #ifdef IMGUI_ENABLE_TEST_ENGINE
2738  if (id != 0)
2739  ImGuiTestEngineHook_ItemAdd(&g, bb, id);
2740 #endif
2741 
2742  // Clipping test
2743  const bool is_clipped = IsClippedEx(bb, id, false);
2744  if (is_clipped)
2745  return false;
2746  //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
2747 
2748  // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
2749  if (IsMouseHoveringRect(bb.Min, bb.Max))
2751  return true;
2752 }
2753 
2754 // This is roughly matching the behavior of internal-facing ItemHoverable()
2755 // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
2756 // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
2758 {
2759  ImGuiContext& g = *GImGui;
2760  ImGuiWindow* window = g.CurrentWindow;
2762  return IsItemFocused();
2763 
2764  // Test for bounding box overlap, as updated as ItemAdd()
2766  return false;
2767  IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
2768 
2769  // Test if we are hovering the right window (our window could be behind another window)
2770  // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
2771  // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
2772  //if (g.HoveredWindow != window)
2773  // return false;
2775  return false;
2776 
2777  // Test if another item is active (e.g. being dragged)
2779  if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
2780  return false;
2781 
2782  // Test if interactions on this window are blocked by an active popup or modal
2783  if (!IsWindowContentHoverable(window, flags))
2784  return false;
2785 
2786  // Test if the item is disabled
2788  return false;
2789 
2790  // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case.
2791  if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
2792  return false;
2793  return true;
2794 }
2795 
2796 // Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
2798 {
2799  ImGuiContext& g = *GImGui;
2800  if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
2801  return false;
2802 
2803  ImGuiWindow* window = g.CurrentWindow;
2804  if (g.HoveredWindow != window)
2805  return false;
2806  if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
2807  return false;
2808  if (!IsMouseHoveringRect(bb.Min, bb.Max))
2809  return false;
2811  return false;
2812  if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
2813  return false;
2814 
2815  SetHoveredID(id);
2816  return true;
2817 }
2818 
2819 bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
2820 {
2821  ImGuiContext& g = *GImGui;
2822  ImGuiWindow* window = g.CurrentWindow;
2823  if (!bb.Overlaps(window->ClipRect))
2824  if (id == 0 || id != g.ActiveId)
2825  if (clip_even_when_logged || !g.LogEnabled)
2826  return true;
2827  return false;
2828 }
2829 
2830 bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
2831 {
2832  ImGuiContext& g = *GImGui;
2833 
2834  const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
2835  window->FocusIdxAllCounter++;
2836  if (is_tab_stop)
2837  window->FocusIdxTabCounter++;
2838 
2839  // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
2840  // Note that we can always TAB out of a widget that doesn't allow tabbing in.
2841  if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
2842  window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
2843 
2844  if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
2845  return true;
2846  if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
2847  {
2848  g.NavJustTabbedId = id;
2849  return true;
2850  }
2851 
2852  return false;
2853 }
2854 
2856 {
2857  window->FocusIdxAllCounter--;
2858  window->FocusIdxTabCounter--;
2859 }
2860 
2861 ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
2862 {
2863  ImGuiContext& g = *GImGui;
2864  ImVec2 content_max;
2865  if (size.x < 0.0f || size.y < 0.0f)
2866  content_max = g.CurrentWindow->Pos + GetContentRegionMax();
2867  if (size.x <= 0.0f)
2868  size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
2869  if (size.y <= 0.0f)
2870  size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
2871  return size;
2872 }
2873 
2874 float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
2875 {
2876  if (wrap_pos_x < 0.0f)
2877  return 0.0f;
2878 
2879  ImGuiWindow* window = GetCurrentWindowRead();
2880  if (wrap_pos_x == 0.0f)
2881  wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
2882  else if (wrap_pos_x > 0.0f)
2883  wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
2884 
2885  return ImMax(wrap_pos_x - pos.x, 1.0f);
2886 }
2887 
2888 void* ImGui::MemAlloc(size_t size)
2889 {
2890  if (ImGuiContext* ctx = GImGui)
2891  ctx->IO.MetricsActiveAllocations++;
2893 }
2894 
2895 void ImGui::MemFree(void* ptr)
2896 {
2897  if (ptr)
2898  if (ImGuiContext* ctx = GImGui)
2899  ctx->IO.MetricsActiveAllocations--;
2901 }
2902 
2904 {
2905  return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
2906 }
2907 
2908 void ImGui::SetClipboardText(const char* text)
2909 {
2910  if (GImGui->IO.SetClipboardTextFn)
2911  GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
2912 }
2913 
2914 const char* ImGui::GetVersion()
2915 {
2916  return IMGUI_VERSION;
2917 }
2918 
2919 // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
2920 // 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
2922 {
2923  return GImGui;
2924 }
2925 
2927 {
2928 #ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
2929  IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
2930 #else
2931  GImGui = ctx;
2932 #endif
2933 }
2934 
2935 // Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
2936 // If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. you may see different structures from what imgui.cpp sees which is highly problematic.
2937 bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert)
2938 {
2939  bool error = false;
2940  if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatched version string!"); }
2941  if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); }
2942  if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); }
2943  if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); }
2944  if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); }
2945  if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); }
2946  return !error;
2947 }
2948 
2949 void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data)
2950 {
2951  GImAllocatorAllocFunc = alloc_func;
2952  GImAllocatorFreeFunc = free_func;
2953  GImAllocatorUserData = user_data;
2954 }
2955 
2957 {
2958  ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
2959  if (GImGui == NULL)
2960  SetCurrentContext(ctx);
2961  Initialize(ctx);
2962  return ctx;
2963 }
2964 
2966 {
2967  if (ctx == NULL)
2968  ctx = GImGui;
2969  Shutdown(ctx);
2970  if (GImGui == ctx)
2971  SetCurrentContext(NULL);
2972  IM_DELETE(ctx);
2973 }
2974 
2976 {
2977  IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
2978  return GImGui->IO;
2979 }
2980 
2982 {
2983  IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
2984  return GImGui->Style;
2985 }
2986 
2987 // Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame()
2989 {
2990  ImGuiContext& g = *GImGui;
2991  return g.DrawData.Valid ? &g.DrawData : NULL;
2992 }
2993 
2995 {
2996  return GImGui->Time;
2997 }
2998 
3000 {
3001  return GImGui->FrameCount;
3002 }
3003 
3005 {
3006  // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'viewport' branches.
3007  return &GImGui->OverlayDrawList;
3008 }
3009 
3011 {
3012  return &GImGui->OverlayDrawList;
3013 }
3014 
3016 {
3017  return &GImGui->DrawListSharedData;
3018 }
3019 
3021 {
3022  // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
3023  // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
3024  // This is because we want ActiveId to be set even when the window is stuck from moving.
3025  ImGuiContext& g = *GImGui;
3026  FocusWindow(window);
3027  SetActiveID(window->MoveId, window);
3028  g.NavDisableHighlight = true;
3029  g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
3030  if (!(window->Flags & ImGuiWindowFlags_NoMove) && !(window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
3031  g.MovingWindow = window;
3032 }
3033 
3034 // Handle mouse moving window
3035 // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
3037 {
3038  ImGuiContext& g = *GImGui;
3039  if (g.MovingWindow != NULL)
3040  {
3041  // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
3042  // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
3043  KeepAliveID(g.ActiveId);
3045  ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
3046  if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
3047  {
3048  ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
3049  if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
3050  {
3051  MarkIniSettingsDirty(moving_window);
3052  SetWindowPos(moving_window, pos, ImGuiCond_Always);
3053  }
3055  }
3056  else
3057  {
3058  ClearActiveID();
3059  g.MovingWindow = NULL;
3060  }
3061  }
3062  else
3063  {
3064  // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
3065  if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
3066  {
3067  KeepAliveID(g.ActiveId);
3068  if (!g.IO.MouseDown[0])
3069  ClearActiveID();
3070  }
3071  }
3072 }
3073 
3074 // Initiate moving window, handle left-click and right-click focus
3076 {
3077  // Initiate moving window
3078  ImGuiContext& g = *GImGui;
3079  if (g.ActiveId != 0 || g.HoveredId != 0)
3080  return;
3081 
3082  // Unless we just made a window/popup appear
3083  if (g.NavWindow && g.NavWindow->Appearing)
3084  return;
3085 
3086  // Click to focus window and start moving (after we're done with all our widgets)
3087  if (g.IO.MouseClicked[0])
3088  {
3089  if (g.HoveredRootWindow != NULL)
3090  {
3094  g.MovingWindow = NULL;
3095  }
3096  else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL)
3097  {
3098  FocusWindow(NULL); // Clicking on void disable focus
3099  }
3100  }
3101 
3102  // With right mouse button we close popups without changing focus
3103  // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger)
3104  if (g.IO.MouseClicked[1])
3105  {
3106  // Find the top-most window between HoveredWindow and the front most Modal Window.
3107  // This is where we can trim the popup stack.
3109  bool hovered_window_above_modal = false;
3110  if (modal == NULL)
3111  hovered_window_above_modal = true;
3112  for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--)
3113  {
3114  ImGuiWindow* window = g.Windows[i];
3115  if (window == modal)
3116  break;
3117  if (window == g.HoveredWindow)
3118  hovered_window_above_modal = true;
3119  }
3120  ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal);
3121  }
3122 }
3123 
3125 {
3126  return (window->Active) && (!window->Hidden);
3127 }
3128 
3130 {
3131  ImGuiContext& g = *GImGui;
3132 
3133  // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
3134  if (IsMousePosValid(&g.IO.MousePos))
3136 
3137  // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
3139  g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
3140  else
3141  g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
3142  if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)
3143  g.NavDisableMouseHover = false;
3144 
3145  g.IO.MousePosPrev = g.IO.MousePos;
3146  for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
3147  {
3148  g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
3149  g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
3151  g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
3152  g.IO.MouseDoubleClicked[i] = false;
3153  if (g.IO.MouseClicked[i])
3154  {
3155  if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
3156  {
3157  ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
3158  if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
3159  g.IO.MouseDoubleClicked[i] = true;
3160  g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click
3161  }
3162  else
3163  {
3164  g.IO.MouseClickedTime[i] = g.Time;
3165  }
3166  g.IO.MouseClickedPos[i] = g.IO.MousePos;
3167  g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
3168  g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
3169  }
3170  else if (g.IO.MouseDown[i])
3171  {
3172  // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
3173  ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
3174  g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
3175  g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
3176  g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
3177  }
3178  if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
3179  g.NavDisableMouseHover = false;
3180  }
3181 }
3182 
3184 {
3185  ImGuiContext& g = *GImGui;
3186  if (!g.HoveredWindow || g.HoveredWindow->Collapsed)
3187  return;
3188  if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
3189  return;
3190 
3191  // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set).
3192  ImGuiWindow* window = g.HoveredWindow;
3193  ImGuiWindow* scroll_window = window;
3194  while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs) && scroll_window->ParentWindow)
3195  scroll_window = scroll_window->ParentWindow;
3196  const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs);
3197 
3198  if (g.IO.MouseWheel != 0.0f)
3199  {
3200  if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
3201  {
3202  // Zoom / Scale window
3203  const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
3204  const float scale = new_font_scale / window->FontWindowScale;
3205  window->FontWindowScale = new_font_scale;
3206 
3207  const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
3208  window->Pos += offset;
3209  window->Size *= scale;
3210  window->SizeFull *= scale;
3211  }
3212  else if (!g.IO.KeyCtrl && scroll_allowed)
3213  {
3214  // Mouse wheel vertical scrolling
3215  float scroll_amount = 5 * scroll_window->CalcFontSize();
3216  scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f);
3217  SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount);
3218  }
3219  }
3220  if (g.IO.MouseWheelH != 0.0f && scroll_allowed && !g.IO.KeyCtrl)
3221  {
3222  // Mouse wheel horizontal scrolling (for hardware that supports it)
3223  float scroll_amount = scroll_window->CalcFontSize();
3224  SetWindowScrollX(scroll_window, scroll_window->Scroll.x - g.IO.MouseWheelH * scroll_amount);
3225  }
3226 }
3227 
3228 // The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
3230 {
3231  ImGuiContext& g = *GImGui;
3232 
3233  // Find the window hovered by mouse:
3234  // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
3235  // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
3236  // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
3238 
3239  // Modal windows prevents cursor from hovering behind them.
3240  ImGuiWindow* modal_window = GetFrontMostPopupModal();
3241  if (modal_window)
3242  if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
3243  g.HoveredRootWindow = g.HoveredWindow = NULL;
3244 
3245  // Disabled mouse?
3247  g.HoveredWindow = g.HoveredRootWindow = NULL;
3248 
3249  // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward.
3250  int mouse_earliest_button_down = -1;
3251  bool mouse_any_down = false;
3252  for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
3253  {
3254  if (g.IO.MouseClicked[i])
3255  g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
3256  mouse_any_down |= g.IO.MouseDown[i];
3257  if (g.IO.MouseDown[i])
3258  if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
3259  mouse_earliest_button_down = i;
3260  }
3261  const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
3262 
3263  // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
3264  // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
3265  const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
3266  if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
3267  g.HoveredWindow = g.HoveredRootWindow = NULL;
3268 
3269  // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app)
3270  if (g.WantCaptureMouseNextFrame != -1)
3272  else
3273  g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
3274 
3275  // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app)
3276  if (g.WantCaptureKeyboardNextFrame != -1)
3278  else
3279  g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
3281  g.IO.WantCaptureKeyboard = true;
3282 
3283  // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible
3284  g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
3285 }
3286 
3288 {
3289  IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
3290  ImGuiContext& g = *GImGui;
3291 
3292 #ifdef IMGUI_ENABLE_TEST_ENGINE
3293  ImGuiTestEngineHook_PreNewFrame(&g);
3294 #endif
3295 
3296  // Check user data
3297  // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument)
3299  IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)");
3300  IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value");
3301  IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
3302  IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
3303  IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting");
3304  IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)");
3305  IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
3306  for (int n = 0; n < ImGuiKey_COUNT; n++)
3307  IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
3308 
3309  // Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP)
3311  IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
3312 
3313  // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
3315  g.IO.ConfigWindowsResizeFromEdges = false;
3316 
3317  // Load settings on first frame (if not explicitly loaded manually before)
3318  if (!g.SettingsLoaded)
3319  {
3321  if (g.IO.IniFilename)
3323  g.SettingsLoaded = true;
3324  }
3325 
3326  // Save settings (with a delay after the last modification, so we don't spam disk too much)
3327  if (g.SettingsDirtyTimer > 0.0f)
3328  {
3330  if (g.SettingsDirtyTimer <= 0.0f)
3331  {
3332  if (g.IO.IniFilename != NULL)
3334  else
3335  g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
3336  g.SettingsDirtyTimer = 0.0f;
3337  }
3338  }
3339 
3340  g.Time += g.IO.DeltaTime;
3341  g.FrameScopeActive = true;
3342  g.FrameCount += 1;
3343  g.TooltipOverrideCount = 0;
3344  g.WindowsActiveCount = 0;
3345 
3346  // Setup current font and draw list
3347  g.IO.Fonts->Locked = true;
3349  IM_ASSERT(g.Font->IsLoaded());
3352 
3353  g.OverlayDrawList.Clear();
3357 
3358  // Mark rendering data as invalid to prevent user who may have a handle on it to use it
3359  g.DrawData.Clear();
3360 
3361  // Drag and drop keep the source ID alive so even if the source disappear our state is consistent
3364 
3365  // Clear reference to active widget if the widget isn't alive anymore
3366  if (!g.HoveredIdPreviousFrame)
3367  g.HoveredIdTimer = 0.0f;
3368  if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
3369  g.HoveredIdNotActiveTimer = 0.0f;
3370  if (g.HoveredId)
3371  g.HoveredIdTimer += g.IO.DeltaTime;
3372  if (g.HoveredId && g.ActiveId != g.HoveredId)
3375  g.HoveredId = 0;
3376  g.HoveredIdAllowOverlap = false;
3377  if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
3378  ClearActiveID();
3379  if (g.ActiveId)
3380  g.ActiveIdTimer += g.IO.DeltaTime;
3385  g.ActiveIdIsAlive = 0;
3386  g.ActiveIdPreviousFrameIsAlive = false;
3387  g.ActiveIdIsJustActivated = false;
3389  g.ScalarAsInputTextId = 0;
3390 
3391  // Drag and drop
3393  g.DragDropAcceptIdCurr = 0;
3394  g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
3395  g.DragDropWithinSourceOrTarget = false;
3396 
3397  // Update keyboard input state
3399  for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
3400  g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;
3401 
3402  // Update gamepad/keyboard directional navigation
3403  NavUpdate();
3404 
3405  // Update mouse input state
3407 
3408  // Calculate frame-rate for the user, as a purely luxurious feature
3412  g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
3413 
3414  // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
3417 
3418  // Background darkening/whitening
3419  if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f))
3420  g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f);
3421  else
3422  g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f);
3423 
3426  g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
3427 
3428  // Mouse wheel scrolling, scale
3429  UpdateMouseWheel();
3430 
3431  // Pressing TAB activate widget focus
3432  if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false))
3433  {
3434  if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
3435  g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
3436  else
3437  g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0;
3438  }
3439  g.NavIdTabCounter = INT_MAX;
3440 
3441  // Mark all windows as not visible
3443  for (int i = 0; i != g.Windows.Size; i++)
3444  {
3445  ImGuiWindow* window = g.Windows[i];
3446  window->WasActive = window->Active;
3447  window->Active = false;
3448  window->WriteAccessed = false;
3449  }
3450 
3451  // Closing the focused window restore focus to the first active root window in descending z-order
3452  if (g.NavWindow && !g.NavWindow->WasActive)
3454 
3455  // No window should be open at the beginning of the frame.
3456  // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
3458  g.BeginPopupStack.resize(0);
3460 
3461  // Create implicit/fallback window - which we will only render it if the user has added something to it.
3462  // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
3463  // This fallback is particularly important as it avoid ImGui:: calls from crashing.
3465  Begin("Debug##Default");
3467 
3468 #ifdef IMGUI_ENABLE_TEST_ENGINE
3469  ImGuiTestEngineHook_PostNewFrame(&g);
3470 #endif
3471 }
3472 
3474 {
3475  ImGuiContext& g = *context;
3477 
3478  // Add .ini handle for ImGuiWindow type
3479  ImGuiSettingsHandler ini_handler;
3480  ini_handler.TypeName = "Window";
3481  ini_handler.TypeHash = ImHash("Window", 0, 0);
3485  g.SettingsHandlers.push_front(ini_handler);
3486 
3487  g.Initialized = true;
3488 }
3489 
3490 // This function is merely here to free heap allocations.
3492 {
3493  // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
3494  ImGuiContext& g = *context;
3495  if (g.IO.Fonts && g.FontAtlasOwnedByContext)
3496  {
3497  g.IO.Fonts->Locked = false;
3498  IM_DELETE(g.IO.Fonts);
3499  }
3500  g.IO.Fonts = NULL;
3501 
3502  // Cleanup of other data are conditional on actually having initialized ImGui.
3503  if (!g.Initialized)
3504  return;
3505 
3506  // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
3507  if (g.SettingsLoaded && g.IO.IniFilename != NULL)
3508  {
3509  ImGuiContext* backup_context = GImGui;
3510  SetCurrentContext(context);
3512  SetCurrentContext(backup_context);
3513  }
3514 
3515  // Clear everything else
3516  for (int i = 0; i < g.Windows.Size; i++)
3517  IM_DELETE(g.Windows[i]);
3518  g.Windows.clear();
3521  g.CurrentWindow = NULL;
3523  g.WindowsById.Clear();
3524  g.NavWindow = NULL;
3525  g.HoveredWindow = NULL;
3526  g.HoveredRootWindow = NULL;
3528  g.MovingWindow = NULL;
3529  g.ColorModifiers.clear();
3530  g.StyleModifiers.clear();
3531  g.FontStack.clear();
3532  g.OpenPopupStack.clear();
3533  g.BeginPopupStack.clear();
3536  g.PrivateClipboard.clear();
3540 
3541  for (int i = 0; i < g.SettingsWindows.Size; i++)
3542  IM_DELETE(g.SettingsWindows[i].Name);
3543  g.SettingsWindows.clear();
3544  g.SettingsHandlers.clear();
3545 
3546  if (g.LogFile && g.LogFile != stdout)
3547  {
3548  fclose(g.LogFile);
3549  g.LogFile = NULL;
3550  }
3551  g.LogClipboard.clear();
3552 
3553  g.Initialized = false;
3554 }
3555 
3556 // FIXME: Add a more explicit sort order in the window structure.
3557 static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
3558 {
3559  const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs;
3560  const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs;
3561  if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
3562  return d;
3564  return d;
3566 }
3567 
3568 static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
3569 {
3570  out_sorted_windows->push_back(window);
3571  if (window->Active)
3572  {
3573  int count = window->DC.ChildWindows.Size;
3574  if (count > 1)
3575  ImQsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
3576  for (int i = 0; i < count; i++)
3577  {
3578  ImGuiWindow* child = window->DC.ChildWindows[i];
3579  if (child->Active)
3580  AddWindowToSortBuffer(out_sorted_windows, child);
3581  }
3582  }
3583 }
3584 
3585 static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
3586 {
3587  if (draw_list->CmdBuffer.empty())
3588  return;
3589 
3590  // Remove trailing command if unused
3591  ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();
3592  if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)
3593  {
3594  draw_list->CmdBuffer.pop_back();
3595  if (draw_list->CmdBuffer.empty())
3596  return;
3597  }
3598 
3599  // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.
3600  IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
3601  IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
3602  IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
3603 
3604  // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
3605  // If this assert triggers because you are drawing lots of stuff manually:
3606  // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents.
3607  // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes.
3608  // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing:
3609  // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
3610  // Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.
3611  // C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.
3612  if (sizeof(ImDrawIdx) == 2)
3613  IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
3614 
3615  out_list->push_back(draw_list);
3616 }
3617 
3618 static void AddWindowToDrawData(ImVector<ImDrawList*>* out_render_list, ImGuiWindow* window)
3619 {
3620  ImGuiContext& g = *GImGui;
3622  AddDrawListToDrawData(out_render_list, window->DrawList);
3623  for (int i = 0; i < window->DC.ChildWindows.Size; i++)
3624  {
3625  ImGuiWindow* child = window->DC.ChildWindows[i];
3626  if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active
3627  AddWindowToDrawData(out_render_list, child);
3628  }
3629 }
3630 
3632 {
3633  ImGuiContext& g = *GImGui;
3634  if (window->Flags & ImGuiWindowFlags_Tooltip)
3636  else
3638 }
3639 
3641 {
3642  int n = Layers[0].Size;
3643  int size = n;
3644  for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
3645  size += Layers[i].Size;
3646  Layers[0].resize(size);
3647  for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
3648  {
3649  ImVector<ImDrawList*>& layer = Layers[layer_n];
3650  if (layer.empty())
3651  continue;
3652  memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
3653  n += layer.Size;
3654  layer.resize(0);
3655  }
3656 }
3657 
3658 static void SetupDrawData(ImVector<ImDrawList*>* draw_lists, ImDrawData* draw_data)
3659 {
3660  ImGuiIO& io = ImGui::GetIO();
3661  draw_data->Valid = true;
3662  draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL;
3663  draw_data->CmdListsCount = draw_lists->Size;
3664  draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
3665  draw_data->DisplayPos = ImVec2(0.0f, 0.0f);
3666  draw_data->DisplaySize = io.DisplaySize;
3667  for (int n = 0; n < draw_lists->Size; n++)
3668  {
3669  draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size;
3670  draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size;
3671  }
3672 }
3673 
3674 // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.
3675 void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
3676 {
3677  ImGuiWindow* window = GetCurrentWindow();
3678  window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
3679  window->ClipRect = window->DrawList->_ClipRectStack.back();
3680 }
3681 
3683 {
3684  ImGuiWindow* window = GetCurrentWindow();
3685  window->DrawList->PopClipRect();
3686  window->ClipRect = window->DrawList->_ClipRectStack.back();
3687 }
3688 
3689 // This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
3691 {
3692  ImGuiContext& g = *GImGui;
3694  if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times.
3695  return;
3696  IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?");
3697 
3698  // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
3700  {
3703  }
3704 
3705  // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
3706  // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
3707  if (g.CurrentWindowStack.Size != 1)
3708  {
3709  if (g.CurrentWindowStack.Size > 1)
3710  {
3711  IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
3712  while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING
3713  End();
3714  }
3715  else
3716  {
3717  IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
3718  }
3719  }
3720 
3721  // Hide implicit/fallback "Debug" window if it hasn't been used
3724  g.CurrentWindow->Active = false;
3725  End();
3726 
3727  // Show CTRL+TAB list window
3728  if (g.NavWindowingTarget)
3730 
3731  // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
3732  if (g.DragDropActive)
3733  {
3734  bool is_delivered = g.DragDropPayload.Delivery;
3736  if (is_delivered || is_elapsed)
3737  ClearDragDrop();
3738  }
3739 
3740  // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing.
3742  {
3744  SetTooltip("...");
3745  g.DragDropWithinSourceOrTarget = false;
3746  }
3747 
3748  // End frame
3749  g.FrameScopeActive = false;
3751 
3752  // Initiate moving window + handle left-click and right-click focus
3754 
3755  // Sort the window list so that all child windows are after their parent
3756  // We cannot do that on FocusWindow() because childs may not exist yet
3759  for (int i = 0; i != g.Windows.Size; i++)
3760  {
3761  ImGuiWindow* window = g.Windows[i];
3762  if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
3763  continue;
3765  }
3766 
3767  IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
3770 
3771  // Unlock font atlas
3772  g.IO.Fonts->Locked = false;
3773 
3774  // Clear Input data for next frame
3775  g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
3777  memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs));
3778 }
3779 
3781 {
3782  ImGuiContext& g = *GImGui;
3784 
3785  if (g.FrameCountEnded != g.FrameCount)
3786  EndFrame();
3788 
3789  // Gather ImDrawList to render (for each active window)
3791  g.DrawDataBuilder.Clear();
3792  ImGuiWindow* windows_to_render_front_most[2];
3793  windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
3794  windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL;
3795  for (int n = 0; n != g.Windows.Size; n++)
3796  {
3797  ImGuiWindow* window = g.Windows[n];
3798  if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1])
3800  }
3801  for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++)
3802  if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window
3803  AddWindowToDrawDataSelectLayer(windows_to_render_front_most[n]);
3805 
3806  // Draw software mouse cursor if requested
3807  if (g.IO.MouseDrawCursor)
3809 
3810  if (!g.OverlayDrawList.VtxBuffer.empty())
3812 
3813  // Setup ImDrawData structure for end-user
3817 
3818  // (Legacy) Call the Render callback function. The current prefer way is to let the user retrieve GetDrawData() and call the render function themselves.
3819 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3820  if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
3822 #endif
3823 }
3824 
3825 // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
3826 // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize)
3827 ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
3828 {
3829  ImGuiContext& g = *GImGui;
3830 
3831  const char* text_display_end;
3832  if (hide_text_after_double_hash)
3833  text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string
3834  else
3835  text_display_end = text_end;
3836 
3837  ImFont* font = g.Font;
3838  const float font_size = g.FontSize;
3839  if (text == text_display_end)
3840  return ImVec2(0.0f, font_size);
3841  ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
3842 
3843  // Cancel out character spacing for the last character of a line (it is baked into glyph->AdvanceX field)
3844  const float font_scale = font_size / font->FontSize;
3845  const float character_spacing_x = 1.0f * font_scale;
3846  if (text_size.x > 0.0f)
3847  text_size.x -= character_spacing_x;
3848  text_size.x = (float)(int)(text_size.x + 0.95f);
3849 
3850  return text_size;
3851 }
3852 
3853 // Helper to calculate coarse clipping of large list of evenly sized items.
3854 // NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
3855 // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
3856 void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
3857 {
3858  ImGuiContext& g = *GImGui;
3859  ImGuiWindow* window = g.CurrentWindow;
3860  if (g.LogEnabled)
3861  {
3862  // If logging is active, do not perform any clipping
3863  *out_items_display_start = 0;
3864  *out_items_display_end = items_count;
3865  return;
3866  }
3867  if (window->SkipItems)
3868  {
3869  *out_items_display_start = *out_items_display_end = 0;
3870  return;
3871  }
3872 
3873  // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect
3874  ImRect unclipped_rect = window->ClipRect;
3875  if (g.NavMoveRequest)
3876  unclipped_rect.Add(g.NavScoringRectScreen);
3877 
3878  const ImVec2 pos = window->DC.CursorPos;
3879  int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
3880  int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
3881 
3882  // When performing a navigation request, ensure we have one item extra in the direction we are moving to
3884  start--;
3886  end++;
3887 
3888  start = ImClamp(start, 0, items_count);
3889  end = ImClamp(end + 1, start, items_count);
3890  *out_items_display_start = start;
3891  *out_items_display_end = end;
3892 }
3893 
3894 // Find window given position, search front-to-back
3895 // FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programatically
3896 // with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is
3897 // called, aka before the next Begin(). Moving window isn't affected.
3898 static void FindHoveredWindow()
3899 {
3900  ImGuiContext& g = *GImGui;
3901 
3902  ImGuiWindow* hovered_window = NULL;
3904  hovered_window = g.MovingWindow;
3905 
3906  ImVec2 padding_regular = g.Style.TouchExtraPadding;
3908  for (int i = g.Windows.Size - 1; i >= 0; i--)
3909  {
3910  ImGuiWindow* window = g.Windows[i];
3911  if (!window->Active || window->Hidden)
3912  continue;
3913  if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
3914  continue;
3915 
3916  // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
3917  ImRect bb(window->OuterRectClipped);
3918  if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize))
3919  bb.Expand(padding_regular);
3920  else
3921  bb.Expand(padding_for_resize_from_edges);
3922  if (!bb.Contains(g.IO.MousePos))
3923  continue;
3924 
3925  // Those seemingly unnecessary extra tests are because the code here is a little different in viewport/docking branches.
3926  if (hovered_window == NULL)
3927  hovered_window = window;
3928  if (hovered_window)
3929  break;
3930  }
3931 
3932  g.HoveredWindow = hovered_window;
3934 
3935 }
3936 
3937 // Test if mouse cursor is hovering given rectangle
3938 // NB- Rectangle is clipped by our current clip setting
3939 // NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
3940 bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
3941 {
3942  ImGuiContext& g = *GImGui;
3943 
3944  // Clip
3945  ImRect rect_clipped(r_min, r_max);
3946  if (clip)
3947  rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
3948 
3949  // Expand for touch input
3950  const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
3951  if (!rect_for_touch.Contains(g.IO.MousePos))
3952  return false;
3953  return true;
3954 }
3955 
3957 {
3958  IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
3959  return GImGui->IO.KeyMap[imgui_key];
3960 }
3961 
3962 // Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]!
3963 bool ImGui::IsKeyDown(int user_key_index)
3964 {
3965  if (user_key_index < 0) return false;
3966  IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown));
3967  return GImGui->IO.KeysDown[user_key_index];
3968 }
3969 
3970 int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)
3971 {
3972  if (t == 0.0f)
3973  return 1;
3974  if (t <= repeat_delay || repeat_rate <= 0.0f)
3975  return 0;
3976  const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate);
3977  return (count > 0) ? count : 0;
3978 }
3979 
3980 int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
3981 {
3982  ImGuiContext& g = *GImGui;
3983  if (key_index < 0) return false;
3984  IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
3985  const float t = g.IO.KeysDownDuration[key_index];
3986  return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate);
3987 }
3988 
3989 bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
3990 {
3991  ImGuiContext& g = *GImGui;
3992  if (user_key_index < 0) return false;
3993  IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
3994  const float t = g.IO.KeysDownDuration[user_key_index];
3995  if (t == 0.0f)
3996  return true;
3997  if (repeat && t > g.IO.KeyRepeatDelay)
3998  return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
3999  return false;
4000 }
4001 
4002 bool ImGui::IsKeyReleased(int user_key_index)
4003 {
4004  ImGuiContext& g = *GImGui;
4005  if (user_key_index < 0) return false;
4006  IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
4007  return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
4008 }
4009 
4010 bool ImGui::IsMouseDown(int button)
4011 {
4012  ImGuiContext& g = *GImGui;
4013  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4014  return g.IO.MouseDown[button];
4015 }
4016 
4018 {
4019  ImGuiContext& g = *GImGui;
4020  for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
4021  if (g.IO.MouseDown[n])
4022  return true;
4023  return false;
4024 }
4025 
4026 bool ImGui::IsMouseClicked(int button, bool repeat)
4027 {
4028  ImGuiContext& g = *GImGui;
4029  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4030  const float t = g.IO.MouseDownDuration[button];
4031  if (t == 0.0f)
4032  return true;
4033 
4034  if (repeat && t > g.IO.KeyRepeatDelay)
4035  {
4036  float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;
4037  if ((ImFmod(t - delay, rate) > rate*0.5f) != (ImFmod(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))
4038  return true;
4039  }
4040 
4041  return false;
4042 }
4043 
4044 bool ImGui::IsMouseReleased(int button)
4045 {
4046  ImGuiContext& g = *GImGui;
4047  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4048  return g.IO.MouseReleased[button];
4049 }
4050 
4052 {
4053  ImGuiContext& g = *GImGui;
4054  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4055  return g.IO.MouseDoubleClicked[button];
4056 }
4057 
4058 bool ImGui::IsMouseDragging(int button, float lock_threshold)
4059 {
4060  ImGuiContext& g = *GImGui;
4061  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4062  if (!g.IO.MouseDown[button])
4063  return false;
4064  if (lock_threshold < 0.0f)
4065  lock_threshold = g.IO.MouseDragThreshold;
4066  return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
4067 }
4068 
4070 {
4071  return GImGui->IO.MousePos;
4072 }
4073 
4074 // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
4076 {
4077  ImGuiContext& g = *GImGui;
4078  if (g.BeginPopupStack.Size > 0)
4079  return g.OpenPopupStack[g.BeginPopupStack.Size-1].OpenMousePos;
4080  return g.IO.MousePos;
4081 }
4082 
4083 // We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position
4084 bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
4085 {
4086  if (mouse_pos == NULL)
4087  mouse_pos = &GImGui->IO.MousePos;
4088  const float MOUSE_INVALID = -256000.0f;
4089  return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID;
4090 }
4091 
4092 // Return the delta from the initial clicking position.
4093 // This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
4094 // NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window.
4095 ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
4096 {
4097  ImGuiContext& g = *GImGui;
4098  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4099  if (lock_threshold < 0.0f)
4100  lock_threshold = g.IO.MouseDragThreshold;
4101  if (g.IO.MouseDown[button])
4102  if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
4103  return g.IO.MousePos - g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment).
4104  return ImVec2(0.0f, 0.0f);
4105 }
4106 
4108 {
4109  ImGuiContext& g = *GImGui;
4110  IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4111  // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
4112  g.IO.MouseClickedPos[button] = g.IO.MousePos;
4113 }
4114 
4116 {
4117  return GImGui->MouseCursor;
4118 }
4119 
4121 {
4122  GImGui->MouseCursor = cursor_type;
4123 }
4124 
4126 {
4127  GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;
4128 }
4129 
4130 void ImGui::CaptureMouseFromApp(bool capture)
4131 {
4132  GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;
4133 }
4134 
4136 {
4137  ImGuiContext& g = *GImGui;
4138  if (g.ActiveId)
4139  {
4140  ImGuiWindow* window = g.CurrentWindow;
4141  return g.ActiveId == window->DC.LastItemId;
4142  }
4143  return false;
4144 }
4145 
4147 {
4148  ImGuiContext& g = *GImGui;
4149  ImGuiWindow* window = g.CurrentWindow;
4150  return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
4151 }
4152 
4154 {
4155  ImGuiContext& g = *GImGui;
4157 }
4158 
4160 {
4161  ImGuiContext& g = *GImGui;
4162  ImGuiWindow* window = g.CurrentWindow;
4163  return g.NavId && !g.NavDisableHighlight && g.NavId == window->DC.LastItemId;
4164 }
4165 
4166 bool ImGui::IsItemClicked(int mouse_button)
4167 {
4168  return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
4169 }
4170 
4172 {
4173  ImGuiContext& g = *GImGui;
4174  return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0;
4175 }
4176 
4178 {
4179  ImGuiContext& g = *GImGui;
4180  return g.ActiveId != 0;
4181 }
4182 
4184 {
4185  ImGuiContext& g = *GImGui;
4186  return g.NavId != 0 && !g.NavDisableHighlight;
4187 }
4188 
4190 {
4191  ImGuiWindow* window = GetCurrentWindowRead();
4192  return window->ClipRect.Overlaps(window->DC.LastItemRect);
4193 }
4194 
4196 {
4197  ImGuiWindow* window = GetCurrentWindowRead();
4198  return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0;
4199 }
4200 
4201 // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
4203 {
4204  ImGuiContext& g = *GImGui;
4205  if (g.HoveredId == g.CurrentWindow->DC.LastItemId)
4206  g.HoveredIdAllowOverlap = true;
4207  if (g.ActiveId == g.CurrentWindow->DC.LastItemId)
4208  g.ActiveIdAllowOverlap = true;
4209 }
4210 
4212 {
4213  ImGuiWindow* window = GetCurrentWindowRead();
4214  return window->DC.LastItemRect.Min;
4215 }
4216 
4218 {
4219  ImGuiWindow* window = GetCurrentWindowRead();
4220  return window->DC.LastItemRect.Max;
4221 }
4222 
4224 {
4225  ImGuiWindow* window = GetCurrentWindowRead();
4226  return window->DC.LastItemRect.GetSize();
4227 }
4228 
4230 {
4231  ImGuiContext& g = *GImGui;
4234  return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
4235 }
4236 
4237 static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
4238 {
4239  ImGuiContext& g = *GImGui;
4240  ImGuiWindow* parent_window = g.CurrentWindow;
4241 
4243  flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
4244 
4245  // Size
4246  const ImVec2 content_avail = GetContentRegionAvail();
4247  ImVec2 size = ImFloor(size_arg);
4248  const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
4249  if (size.x <= 0.0f)
4250  size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues)
4251  if (size.y <= 0.0f)
4252  size.y = ImMax(content_avail.y + size.y, 4.0f);
4253  SetNextWindowSize(size);
4254 
4255  // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
4256  char title[256];
4257  if (name)
4258  ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s_%08X", parent_window->Name, name, id);
4259  else
4260  ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id);
4261 
4262  const float backup_border_size = g.Style.ChildBorderSize;
4263  if (!border)
4264  g.Style.ChildBorderSize = 0.0f;
4265  bool ret = Begin(title, NULL, flags);
4266  g.Style.ChildBorderSize = backup_border_size;
4267 
4268  ImGuiWindow* child_window = g.CurrentWindow;
4269  child_window->ChildId = id;
4270  child_window->AutoFitChildAxises = auto_fit_axises;
4271 
4272  // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
4273  // While this is not really documented/defined, it seems that the expected thing to do.
4274  parent_window->DC.CursorPos = child_window->Pos;
4275 
4276  // Process navigation-in immediately so NavInit can run on first frame
4277  if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll))
4278  {
4279  FocusWindow(child_window);
4280  NavInitWindow(child_window, false);
4281  SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
4283  }
4284  return ret;
4285 }
4286 
4287 bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
4288 {
4289  ImGuiWindow* window = GetCurrentWindow();
4290  return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
4291 }
4292 
4293 bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
4294 {
4295  IM_ASSERT(id != 0);
4296  return BeginChildEx(NULL, id, size_arg, border, extra_flags);
4297 }
4298 
4300 {
4301  ImGuiContext& g = *GImGui;
4302  ImGuiWindow* window = g.CurrentWindow;
4303 
4304  IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
4305  if (window->BeginCount > 1)
4306  {
4307  End();
4308  }
4309  else
4310  {
4311  ImVec2 sz = window->Size;
4312  if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
4313  sz.x = ImMax(4.0f, sz.x);
4314  if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
4315  sz.y = ImMax(4.0f, sz.y);
4316  End();
4317 
4318  ImGuiWindow* parent_window = g.CurrentWindow;
4319  ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
4320  ItemSize(sz);
4321  if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
4322  {
4323  ItemAdd(bb, window->ChildId);
4324  RenderNavHighlight(bb, window->ChildId);
4325 
4326  // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
4327  if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow)
4329  }
4330  else
4331  {
4332  // Not navigable into
4333  ItemAdd(bb, 0);
4334  }
4335  }
4336 }
4337 
4338 // Helper to create a child window / scrolling region that looks like a normal widget frame.
4339 bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
4340 {
4341  ImGuiContext& g = *GImGui;
4342  const ImGuiStyle& style = g.Style;
4347  bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
4348  PopStyleVar(3);
4349  PopStyleColor();
4350  return ret;
4351 }
4352 
4354 {
4355  EndChild();
4356 }
4357 
4358 // Save and compare stack sizes on Begin()/End() to detect usage errors
4359 static void CheckStacksSize(ImGuiWindow* window, bool write)
4360 {
4361  // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
4362  ImGuiContext& g = *GImGui;
4363  short* p_backup = &window->DC.StackSizesBackup[0];
4364  { int current = window->IDStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop()
4365  { int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup()
4366  { int current = g.BeginPopupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup()
4367  // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
4368  { int current = g.ColorModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor()
4369  { int current = g.StyleModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar()
4370  { int current = g.FontStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushFont/PopFont Mismatch!"); p_backup++; } // Too few or too many PopFont()
4371  IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
4372 }
4373 
4374 static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
4375 {
4376  window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
4377  window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
4378  window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
4379 }
4380 
4382 {
4383  ImGuiContext& g = *GImGui;
4384  return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id);
4385 }
4386 
4388 {
4389  ImGuiID id = ImHash(name, 0);
4390  return FindWindowByID(id);
4391 }
4392 
4393 static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
4394 {
4395  ImGuiContext& g = *GImGui;
4396 
4397  // Create window the first time
4398  ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
4399  window->Flags = flags;
4400  g.WindowsById.SetVoidPtr(window->ID, window);
4401 
4402  // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
4403  window->Pos = ImVec2(60, 60);
4404 
4405  // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
4406  if (!(flags & ImGuiWindowFlags_NoSavedSettings))
4407  if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
4408  {
4409  // Retrieve settings from .ini file
4410  window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
4412  window->Pos = ImFloor(settings->Pos);
4413  window->Collapsed = settings->Collapsed;
4414  if (ImLengthSqr(settings->Size) > 0.00001f)
4415  size = ImFloor(settings->Size);
4416  }
4417  window->Size = window->SizeFull = window->SizeFullAtLastBegin = ImFloor(size);
4418  window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
4419 
4420  if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
4421  {
4422  window->AutoFitFramesX = window->AutoFitFramesY = 2;
4423  window->AutoFitOnlyGrows = false;
4424  }
4425  else
4426  {
4427  if (window->Size.x <= 0.0f)
4428  window->AutoFitFramesX = 2;
4429  if (window->Size.y <= 0.0f)
4430  window->AutoFitFramesY = 2;
4431  window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
4432  }
4433 
4434  g.WindowsFocusOrder.push_back(window);
4436  g.Windows.push_front(window); // Quite slow but rare and only once
4437  else
4438  g.Windows.push_back(window);
4439  return window;
4440 }
4441 
4443 {
4444  ImGuiContext& g = *GImGui;
4446  {
4447  // Using -1,-1 on either X/Y axis to preserve the current size.
4449  new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
4450  new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
4452  {
4453  ImGuiSizeCallbackData data;
4455  data.Pos = window->Pos;
4456  data.CurrentSize = window->SizeFull;
4457  data.DesiredSize = new_size;
4458  g.NextWindowData.SizeCallback(&data);
4459  new_size = data.DesiredSize;
4460  }
4461  }
4462 
4463  // Minimum size
4465  {
4466  new_size = ImMax(new_size, g.Style.WindowMinSize);
4467  new_size.y = ImMax(new_size.y, window->TitleBarHeight() + window->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows
4468  }
4469  return new_size;
4470 }
4471 
4473 {
4474  if (window->Collapsed)
4475  return window->SizeContents;
4476  if (window->Hidden && window->HiddenFramesForResize == 0 && window->HiddenFramesRegular > 0)
4477  return window->SizeContents;
4478 
4479  ImVec2 sz;
4480  sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
4481  sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
4482  return sz + window->WindowPadding;
4483 }
4484 
4485 static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
4486 {
4487  ImGuiContext& g = *GImGui;
4488  ImGuiStyle& style = g.Style;
4489  if (window->Flags & ImGuiWindowFlags_Tooltip)
4490  {
4491  // Tooltip always resize
4492  return size_contents;
4493  }
4494  else
4495  {
4496  // When the window cannot fit all contents (either because of constraints, either because screen is too small): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding.
4497  const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0;
4498  const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
4499  ImVec2 size_min = style.WindowMinSize;
4500  if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups)
4501  size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
4502  ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
4503  ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
4504  if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
4505  size_auto_fit.y += style.ScrollbarSize;
4506  if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
4507  size_auto_fit.x += style.ScrollbarSize;
4508  return size_auto_fit;
4509  }
4510 }
4511 
4513 {
4514  ImVec2 size_contents = CalcSizeContents(window);
4515  return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents));
4516 }
4517 
4519 {
4520  return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
4521 }
4522 
4524 {
4525  return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
4526 }
4527 
4528 static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
4529 {
4530  ImGuiContext& g = *GImGui;
4531  ImVec2 scroll = window->Scroll;
4532  if (window->ScrollTarget.x < FLT_MAX)
4533  {
4534  float cr_x = window->ScrollTargetCenterRatio.x;
4535  scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
4536  }
4537  if (window->ScrollTarget.y < FLT_MAX)
4538  {
4539  // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding.
4540  float cr_y = window->ScrollTargetCenterRatio.y;
4541  float target_y = window->ScrollTarget.y;
4542  if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y)
4543  target_y = 0.0f;
4544  if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y)
4545  target_y = window->SizeContents.y;
4546  scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);
4547  }
4548  scroll = ImMax(scroll, ImVec2(0.0f, 0.0f));
4549  if (!window->Collapsed && !window->SkipItems)
4550  {
4551  scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window));
4552  scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window));
4553  }
4554  return scroll;
4555 }
4556 
4558 {
4560  return ImGuiCol_PopupBg;
4561  if (flags & ImGuiWindowFlags_ChildWindow)
4562  return ImGuiCol_ChildBg;
4563  return ImGuiCol_WindowBg;
4564 }
4565 
4566 static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
4567 {
4568  ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left
4569  ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
4570  ImVec2 size_expected = pos_max - pos_min;
4571  ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected);
4572  *out_pos = pos_min;
4573  if (corner_norm.x == 0.0f)
4574  out_pos->x -= (size_constrained.x - size_expected.x);
4575  if (corner_norm.y == 0.0f)
4576  out_pos->y -= (size_constrained.y - size_expected.y);
4577  *out_size = size_constrained;
4578 }
4579 
4581 {
4584  int AngleMin12, AngleMax12;
4585 };
4586 
4588 {
4589  { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower right
4590  { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower left
4591  { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper left
4592  { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right
4593 };
4594 
4595 static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
4596 {
4597  ImRect rect = window->Rect();
4598  if (thickness == 0.0f) rect.Max -= ImVec2(1,1);
4599  if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness);
4600  if (border_n == 1) return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding);
4601  if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness);
4602  if (border_n == 3) return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding);
4603  IM_ASSERT(0);
4604  return ImRect();
4605 }
4606 
4607 // Handle resize for: Resize Grips, Borders, Gamepad
4608 static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
4609 {
4610  ImGuiContext& g = *GImGui;
4611  ImGuiWindowFlags flags = window->Flags;
4612  if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
4613  return;
4614  if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
4615  return;
4616 
4617  const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
4618  const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
4619  const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f);
4620  const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f;
4621 
4622  ImVec2 pos_target(FLT_MAX, FLT_MAX);
4623  ImVec2 size_target(FLT_MAX, FLT_MAX);
4624 
4625  // Manual resize grips
4626  PushID("#RESIZE");
4627  for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
4628  {
4629  const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
4630  const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
4631 
4632  // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
4633  ImRect resize_rect(corner - grip.InnerDir * grip_hover_outer_size, corner + grip.InnerDir * grip_hover_inner_size);
4634  if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
4635  if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
4636  bool hovered, held;
4637  ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
4638  //GetOverlayDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
4639  if (hovered || held)
4641 
4642  if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
4643  {
4644  // Manual auto-fit when double-clicking
4645  size_target = CalcSizeAfterConstraint(window, size_auto_fit);
4646  ClearActiveID();
4647  }
4648  else if (held)
4649  {
4650  // Resize from any of the four corners
4651  // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
4652  ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPos); // Corner of the window corresponding to our corner grip
4653  CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target);
4654  }
4655  if (resize_grip_n == 0 || held || hovered)
4656  resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
4657  }
4658  for (int border_n = 0; border_n < resize_border_count; border_n++)
4659  {
4660  bool hovered, held;
4661  ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS);
4662  ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
4663  //GetOverlayDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
4664  if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
4665  {
4667  if (held) *border_held = border_n;
4668  }
4669  if (held)
4670  {
4671  ImVec2 border_target = window->Pos;
4672  ImVec2 border_posn;
4673  if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
4674  if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
4675  if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
4676  if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
4677  CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
4678  }
4679  }
4680  PopID();
4681 
4682  // Navigation resize (keyboard/gamepad)
4683  if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
4684  {
4685  ImVec2 nav_resize_delta;
4690  if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
4691  {
4692  const float NAV_RESIZE_SPEED = 600.0f;
4693  nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
4694  g.NavWindowingToggleLayer = false;
4695  g.NavDisableMouseHover = true;
4696  resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
4697  // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
4698  size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
4699  }
4700  }
4701 
4702  // Apply back modified position/size to window
4703  if (size_target.x != FLT_MAX)
4704  {
4705  window->SizeFull = size_target;
4706  MarkIniSettingsDirty(window);
4707  }
4708  if (pos_target.x != FLT_MAX)
4709  {
4710  window->Pos = ImFloor(pos_target);
4711  MarkIniSettingsDirty(window);
4712  }
4713 
4714  window->Size = window->SizeFull;
4715 }
4716 
4718 {
4719  window->ParentWindow = parent_window;
4720  window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
4721  if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
4722  window->RootWindow = parent_window->RootWindow;
4723  if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
4726  window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
4727 }
4728 
4729 // Push a new ImGui window to add widgets to.
4730 // - 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.
4731 // - Begin/End can be called multiple times during the frame with the same window name to append content.
4732 // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
4733 // 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.
4734 // - 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.
4735 // - Passing 'bool* p_open' 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.
4736 bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
4737 {
4738  ImGuiContext& g = *GImGui;
4739  const ImGuiStyle& style = g.Style;
4740  IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required
4741  IM_ASSERT(g.FrameScopeActive); // Forgot to call ImGui::NewFrame()
4742  IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
4743 
4744  // Find or create
4745  ImGuiWindow* window = FindWindowByName(name);
4746  const bool window_just_created = (window == NULL);
4747  if (window_just_created)
4748  {
4749  ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
4750  window = CreateNewWindow(name, size_on_first_use, flags);
4751  }
4752 
4753  // Automatically disable manual moving/resizing when NoInputs is set
4754  if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
4756 
4757  if (flags & ImGuiWindowFlags_NavFlattened)
4759 
4760  const int current_frame = g.FrameCount;
4761  const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
4762 
4763  // Update Flags, LastFrameActive, BeginOrderXXX fields
4764  if (first_begin_of_the_frame)
4765  window->Flags = (ImGuiWindowFlags)flags;
4766  else
4767  flags = window->Flags;
4768 
4769  // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
4770  ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
4771  ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
4772  IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
4773  window->HasCloseButton = (p_open != NULL);
4774 
4775  // Update the Appearing flag
4776  bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
4777  const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0);
4778  if (flags & ImGuiWindowFlags_Popup)
4779  {
4781  window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
4782  window_just_activated_by_user |= (window != popup_ref.Window);
4783  }
4784  window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize);
4785  if (window->Appearing)
4787 
4788  // Add to stack
4789  g.CurrentWindowStack.push_back(window);
4790  SetCurrentWindow(window);
4791  CheckStacksSize(window, true);
4792  if (flags & ImGuiWindowFlags_Popup)
4793  {
4795  popup_ref.Window = window;
4796  g.BeginPopupStack.push_back(popup_ref);
4797  window->PopupId = popup_ref.PopupId;
4798  }
4799 
4800  if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow))
4801  window->NavLastIds[0] = 0;
4802 
4803  // Process SetNextWindow***() calls
4804  bool window_pos_set_by_api = false;
4805  bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
4806  if (g.NextWindowData.PosCond)
4807  {
4808  window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
4809  if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
4810  {
4811  // May be processed on the next frame if this is our first frame and we are measuring size
4812  // FIXME: Look into removing the branch so everything can go through this same code path for consistency.
4816  }
4817  else
4818  {
4820  }
4821  }
4822  if (g.NextWindowData.SizeCond)
4823  {
4824  window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
4825  window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
4827  }
4829  {
4830  // Adjust passed "client size" to become a "window size"
4832  if (window->SizeContentsExplicit.y != 0.0f)
4833  window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight();
4834  }
4835  else if (first_begin_of_the_frame)
4836  {
4837  window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
4838  }
4841  if (g.NextWindowData.FocusCond)
4842  FocusWindow(window);
4843  if (window->Appearing)
4845 
4846  // When reusing window again multiple times a frame, just append content (don't need to setup again)
4847  if (first_begin_of_the_frame)
4848  {
4849  // Initialize
4850  const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
4851  UpdateWindowParentAndRootLinks(window, flags, parent_window);
4852 
4853  window->Active = true;
4854  window->BeginOrderWithinParent = 0;
4855  window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
4856  window->BeginCount = 0;
4857  window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
4858  window->LastFrameActive = current_frame;
4859  window->IDStack.resize(1);
4860 
4861  // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged).
4862  // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere.
4863  bool window_title_visible_elsewhere = false;
4864  if (g.NavWindowingList != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
4865  window_title_visible_elsewhere = true;
4866  if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
4867  {
4868  size_t buf_len = (size_t)window->NameBufLen;
4869  window->Name = ImStrdupcpy(window->Name, &buf_len, name);
4870  window->NameBufLen = (int)buf_len;
4871  }
4872 
4873  // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
4874 
4875  // Update contents size from last frame for auto-fitting (or use explicit size)
4876  window->SizeContents = CalcSizeContents(window);
4877  if (window->HiddenFramesRegular > 0)
4878  window->HiddenFramesRegular--;
4879  if (window->HiddenFramesForResize > 0)
4880  window->HiddenFramesForResize--;
4881 
4882  // Hide new windows for one frame until they calculate their size
4883  if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
4884  window->HiddenFramesForResize = 1;
4885 
4886  // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
4887  // We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
4888  if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
4889  {
4890  window->HiddenFramesForResize = 1;
4892  {
4893  if (!window_size_x_set_by_api)
4894  window->Size.x = window->SizeFull.x = 0.f;
4895  if (!window_size_y_set_by_api)
4896  window->Size.y = window->SizeFull.y = 0.f;
4897  window->SizeContents = ImVec2(0.f, 0.f);
4898  }
4899  }
4900 
4901  SetCurrentWindow(window);
4902 
4903  // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies)
4904  window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
4905  window->WindowPadding = style.WindowPadding;
4906  if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
4907  window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
4910 
4911  // Collapse window by double-clicking on title bar
4912  // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
4913  if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
4914  {
4915  // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
4916  ImRect title_bar_rect = window->TitleBarRect();
4917  if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])
4918  window->WantCollapseToggle = true;
4919  if (window->WantCollapseToggle)
4920  {
4921  window->Collapsed = !window->Collapsed;
4922  MarkIniSettingsDirty(window);
4923  FocusWindow(window);
4924  }
4925  }
4926  else
4927  {
4928  window->Collapsed = false;
4929  }
4930  window->WantCollapseToggle = false;
4931 
4932  // SIZE
4933 
4934  // Calculate auto-fit size, handle automatic resize
4935  const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
4936  ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
4937  if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
4938  {
4939  // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
4940  if (!window_size_x_set_by_api)
4941  window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
4942  if (!window_size_y_set_by_api)
4943  window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
4944  }
4945  else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
4946  {
4947  // Auto-fit may only grow window during the first few frames
4948  // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
4949  if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
4950  window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
4951  if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
4952  window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
4953  if (!window->Collapsed)
4954  MarkIniSettingsDirty(window);
4955  }
4956 
4957  // Apply minimum/maximum window size constraints and final size
4958  window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
4959  window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
4960 
4961  // SCROLLBAR STATUS
4962 
4963  // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size).
4964  if (!window->Collapsed)
4965  {
4966  // When reading the current size we need to read it after size constraints have been applied
4967  float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
4968  float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
4969  window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
4970  window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
4971  if (window->ScrollbarX && !window->ScrollbarY)
4972  window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
4973  window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
4974  }
4975 
4976  // POSITION
4977 
4978  // Popup latch its initial position, will position itself when it appears next frame
4979  if (window_just_activated_by_user)
4980  {
4982  if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
4983  window->Pos = g.BeginPopupStack.back().OpenPopupPos;
4984  }
4985 
4986  // Position child window
4987  if (flags & ImGuiWindowFlags_ChildWindow)
4988  {
4989  IM_ASSERT(parent_window->Active);
4990  window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
4991  parent_window->DC.ChildWindows.push_back(window);
4992  if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
4993  window->Pos = parent_window->DC.CursorPos;
4994  }
4995 
4996  const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0);
4997  if (window_pos_with_pivot)
4998  SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering)
4999  else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
5000  window->Pos = FindBestWindowPosForPopup(window);
5001  else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
5002  window->Pos = FindBestWindowPosForPopup(window);
5003  else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
5004  window->Pos = FindBestWindowPosForPopup(window);
5005 
5006  // Clamp position so it stays visible
5007  if (!(flags & ImGuiWindowFlags_ChildWindow))
5008  {
5009  if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && 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.
5010  {
5011  ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
5012  ImVec2 size_for_clamping = ((g.IO.ConfigWindowsMoveFromTitleBarOnly) && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size;
5013  window->Pos = ImMax(window->Pos + size_for_clamping, padding) - size_for_clamping;
5014  window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding);
5015  }
5016  }
5017  window->Pos = ImFloor(window->Pos);
5018 
5019  // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
5020  window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
5021 
5022  // Prepare for item focus requests
5023  window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
5024  window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
5025  window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
5026  window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
5027 
5028  // Apply scrolling
5029  window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
5030  window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
5031 
5032  // Apply window focus (new and reactivated windows are moved to front)
5033  bool want_focus = false;
5034  if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
5035  if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup))
5036  want_focus = true;
5037 
5038  // Handle manual resize: Resize Grips, Borders, Gamepad
5039  int border_held = -1;
5040  ImU32 resize_grip_col[4] = { 0 };
5041  const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
5042  const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
5043  if (!window->Collapsed)
5044  UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
5045 
5046  // Default item width. Make it proportional to window size if window manually resizes
5047  if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
5048  window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
5049  else
5050  window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
5051 
5052  // DRAWING
5053 
5054  // Setup draw list and outer clipping rectangle
5055  window->DrawList->Clear();
5058  ImRect viewport_rect(GetViewportRect());
5059  if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
5060  PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
5061  else
5062  PushClipRect(viewport_rect.Min, viewport_rect.Max, true);
5063 
5064  // Draw modal window background (darkens what is behind them, all viewports)
5065  const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0;
5066  const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
5067  if (dim_bg_for_modal || dim_bg_for_window_list)
5068  {
5069  const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
5070  window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
5071  }
5072 
5073  // Draw navigation selection/windowing rectangle background
5074  if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
5075  {
5076  ImRect bb = window->Rect();
5077  bb.Expand(g.FontSize);
5078  if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
5080  }
5081 
5082  // Draw window + handle manual resize
5083  const float window_rounding = window->WindowRounding;
5084  const float window_border_size = window->WindowBorderSize;
5085  const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
5086  const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
5087  const ImRect title_bar_rect = window->TitleBarRect();
5088  if (window->Collapsed)
5089  {
5090  // Title bar only
5091  float backup_border_size = style.FrameBorderSize;
5093  ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
5094  RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
5095  g.Style.FrameBorderSize = backup_border_size;
5096  }
5097  else
5098  {
5099  // Window background
5100  if (!(flags & ImGuiWindowFlags_NoBackground))
5101  {
5103  if (g.NextWindowData.BgAlphaCond != 0)
5105  window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
5106  }
5108 
5109  // Title bar
5110  if (!(flags & ImGuiWindowFlags_NoTitleBar))
5111  {
5112  ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
5113  window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
5114  }
5115 
5116  // Menu bar
5117  if (flags & ImGuiWindowFlags_MenuBar)
5118  {
5119  ImRect menu_bar_rect = window->MenuBarRect();
5120  menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
5121  window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
5122  if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
5123  window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
5124  }
5125 
5126  // Scrollbars
5127  if (window->ScrollbarX)
5129  if (window->ScrollbarY)
5131 
5132  // Render resize grips (after their input handling so we don't have a frame of latency)
5133  if (!(flags & ImGuiWindowFlags_NoResize))
5134  {
5135  for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
5136  {
5137  const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
5138  const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
5139  window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size)));
5140  window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size)));
5141  window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
5142  window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
5143  }
5144  }
5145 
5146  // Borders
5147  if (window_border_size > 0.0f && !(flags & ImGuiWindowFlags_NoBackground))
5148  window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), window_rounding, ImDrawCornerFlags_All, window_border_size);
5149  if (border_held != -1)
5150  {
5151  ImRect border = GetResizeBorderRect(window, border_held, grip_draw_size, 0.0f);
5152  window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size));
5153  }
5154  if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar))
5155  window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize, -1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
5156  }
5157 
5158  // Draw navigation selection/windowing rectangle border
5159  if (g.NavWindowingTargetAnim == window)
5160  {
5161  float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
5162  ImRect bb = window->Rect();
5163  bb.Expand(g.FontSize);
5164  if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
5165  {
5166  bb.Expand(-g.FontSize - 1.0f);
5167  rounding = window->WindowRounding;
5168  }
5170  }
5171 
5172  // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
5173  window->SizeFullAtLastBegin = window->SizeFull;
5174 
5175  // Update various regions. Variables they depends on are set above in this function.
5176  // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
5177  window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
5178  window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
5179  window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x));
5180  window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y));
5181 
5182  // Setup drawing context
5183  // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
5184  window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
5185  window->DC.GroupOffset.x = 0.0f;
5186  window->DC.ColumnsOffset.x = 0.0f;
5187  window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);
5188  window->DC.CursorPos = window->DC.CursorStartPos;
5189  window->DC.CursorPosPrevLine = window->DC.CursorPos;
5190  window->DC.CursorMaxPos = window->DC.CursorStartPos;
5191  window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
5192  window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
5193  window->DC.NavHideHighlightOneFrame = false;
5194  window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
5195  window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
5196  window->DC.NavLayerActiveMaskNext = 0x00;
5197  window->DC.MenuBarAppending = false;
5198  window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
5199  window->DC.ChildWindows.resize(0);
5201  window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
5202  window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
5203  window->DC.ItemWidth = window->ItemWidthDefault;
5204  window->DC.TextWrapPos = -1.0f; // disabled
5205  window->DC.ItemFlagsStack.resize(0);
5206  window->DC.ItemWidthStack.resize(0);
5207  window->DC.TextWrapPosStack.resize(0);
5208  window->DC.ColumnsSet = NULL;
5209  window->DC.TreeDepth = 0;
5210  window->DC.TreeDepthMayJumpToParentOnPop = 0x00;
5211  window->DC.StateStorage = &window->StateStorage;
5212  window->DC.GroupStack.resize(0);
5213  window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
5214 
5215  if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags))
5216  {
5217  window->DC.ItemFlags = parent_window->DC.ItemFlags;
5218  window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5219  }
5220 
5221  if (window->AutoFitFramesX > 0)
5222  window->AutoFitFramesX--;
5223  if (window->AutoFitFramesY > 0)
5224  window->AutoFitFramesY--;
5225 
5226  // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
5227  if (want_focus)
5228  {
5229  FocusWindow(window);
5230  NavInitWindow(window, false);
5231  }
5232 
5233  // Title bar
5234  if (!(flags & ImGuiWindowFlags_NoTitleBar))
5235  {
5236  // Close & collapse button are on layer 1 (same as menus) and don't default focus
5237  const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
5240  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
5241 
5242  // Collapse button
5243  if (!(flags & ImGuiWindowFlags_NoCollapse))
5244  if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos))
5245  window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
5246 
5247  // Close button
5248  if (p_open != NULL)
5249  {
5250  const float pad = style.FramePadding.y;
5251  const float rad = g.FontSize * 0.5f;
5252  if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1))
5253  *p_open = false;
5254  }
5255 
5257  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
5258  window->DC.ItemFlags = item_flags_backup;
5259 
5260  // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
5261  // FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
5262  const char* UNSAVED_DOCUMENT_MARKER = "*";
5263  float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
5264  ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
5265  ImRect text_r = title_bar_rect;
5266  float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
5267  float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
5268  if (style.WindowTitleAlign.x > 0.0f)
5269  pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
5270  text_r.Min.x += pad_left;
5271  text_r.Max.x -= pad_right;
5272  ImRect clip_rect = text_r;
5273  clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
5274  RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
5276  {
5277  ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
5278  ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
5279  RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
5280  }
5281  }
5282 
5283  // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
5284  window->OuterRectClipped = window->Rect();
5285  window->OuterRectClipped.ClipWith(window->ClipRect);
5286 
5287  // Pressing CTRL+C while holding on a window copy its content to the clipboard
5288  // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
5289  // Maybe we can support CTRL+C on every element?
5290  /*
5291  if (g.ActiveId == move_id)
5292  if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
5293  LogToClipboard();
5294  */
5295 
5296  // Inner rectangle
5297  // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
5298  // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
5299  window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
5300  window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
5301  window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize;
5302  window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize;
5303  //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE);
5304 
5305  // Inner clipping rectangle
5306  // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
5307  window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5308  window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
5309  window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5310  window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
5311 
5312  // After Begin() we fill the last item / hovered data based on title bar data. It is a standard behavior (to allow creation of context menus on title bar only, etc.).
5313  window->DC.LastItemId = window->MoveId;
5314  window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
5315  window->DC.LastItemRect = title_bar_rect;
5316  }
5317 
5318  PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
5319 
5320  // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
5321  if (first_begin_of_the_frame)
5322  window->WriteAccessed = false;
5323 
5324  window->BeginCount++;
5325  g.NextWindowData.Clear();
5326 
5327  if (flags & ImGuiWindowFlags_ChildWindow)
5328  {
5329  // Child window can be out of sight and have "negative" clip windows.
5330  // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar).
5331  IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);
5332 
5333  if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
5334  if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
5335  window->HiddenFramesRegular = 1;
5336 
5337  // Completely hide along with parent or if parent is collapsed
5338  if (parent_window && (parent_window->Collapsed || parent_window->Hidden))
5339  window->HiddenFramesRegular = 1;
5340  }
5341 
5342  // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point)
5343  if (style.Alpha <= 0.0f)
5344  window->HiddenFramesRegular = 1;
5345 
5346  // Update the Hidden flag
5347  window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize > 0);
5348 
5349  // Return false if we don't intend to display anything to allow user to perform an early out optimization
5350  window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0;
5351 
5352  return !window->SkipItems;
5353 }
5354 
5355 // Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead.
5356 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5357 bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags)
5358 {
5359  // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file.
5360  if (size_first_use.x != 0.0f || size_first_use.y != 0.0f)
5361  SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver);
5362 
5363  // Old API feature: override the window background alpha with a parameter.
5364  if (bg_alpha_override >= 0.0f)
5365  SetNextWindowBgAlpha(bg_alpha_override);
5366 
5367  return Begin(name, p_open, flags);
5368 }
5369 #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5370 
5372 {
5373  ImGuiContext& g = *GImGui;
5374 
5376  {
5377  IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!");
5378  return; // FIXME-ERRORHANDLING
5379  }
5381 
5382  ImGuiWindow* window = g.CurrentWindow;
5383 
5384  if (window->DC.ColumnsSet != NULL)
5385  EndColumns();
5386  PopClipRect(); // Inner window clip rectangle
5387 
5388  // Stop logging
5389  if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
5390  LogFinish();
5391 
5392  // Pop from window stack
5394  if (window->Flags & ImGuiWindowFlags_Popup)
5396  CheckStacksSize(window, false);
5398 }
5399 
5401 {
5402  ImGuiContext& g = *GImGui;
5403  if (g.WindowsFocusOrder.back() == window)
5404  return;
5405  for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window
5406  if (g.WindowsFocusOrder[i] == window)
5407  {
5408  memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*));
5409  g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window;
5410  break;
5411  }
5412 }
5413 
5415 {
5416  ImGuiContext& g = *GImGui;
5417  ImGuiWindow* current_front_window = g.Windows.back();
5418  if (current_front_window == window || current_front_window->RootWindow == window)
5419  return;
5420  for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window
5421  if (g.Windows[i] == window)
5422  {
5423  memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
5424  g.Windows[g.Windows.Size - 1] = window;
5425  break;
5426  }
5427 }
5428 
5430 {
5431  ImGuiContext& g = *GImGui;
5432  if (g.Windows[0] == window)
5433  return;
5434  for (int i = 0; i < g.Windows.Size; i++)
5435  if (g.Windows[i] == window)
5436  {
5437  memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
5438  g.Windows[0] = window;
5439  break;
5440  }
5441 }
5442 
5443 // Moving window to front of display and set focus (which happens to be back of our sorted list)
5445 {
5446  ImGuiContext& g = *GImGui;
5447 
5448  if (g.NavWindow != window)
5449  {
5450  g.NavWindow = window;
5451  if (window && g.NavDisableMouseHover)
5452  g.NavMousePosDirty = true;
5453  g.NavInitRequest = false;
5454  g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
5455  g.NavIdIsAlive = false;
5457  //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL);
5458  }
5459 
5460  // Passing NULL allow to disable keyboard focus
5461  if (!window)
5462  return;
5463 
5464  // Move the root window to the top of the pile
5465  if (window->RootWindow)
5466  window = window->RootWindow;
5467 
5468  // Steal focus on active widgets
5469  if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
5470  if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
5471  ClearActiveID();
5472 
5473  // Bring to front
5474  BringWindowToFocusFront(window);
5476  BringWindowToDisplayFront(window);
5477 }
5478 
5480 {
5481  ImGuiContext& g = *GImGui;
5482  for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--)
5483  {
5484  // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
5485  ImGuiWindow* window = g.WindowsFocusOrder[i];
5486  if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow))
5488  {
5489  ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
5490  FocusWindow(focus_window);
5491  return;
5492  }
5493  }
5494 }
5495 
5496 void ImGui::PushItemWidth(float item_width)
5497 {
5498  ImGuiWindow* window = GetCurrentWindow();
5499  window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
5500  window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
5501 }
5502 
5503 void ImGui::PushMultiItemsWidths(int components, float w_full)
5504 {
5505  ImGuiWindow* window = GetCurrentWindow();
5506  const ImGuiStyle& style = GImGui->Style;
5507  if (w_full <= 0.0f)
5508  w_full = CalcItemWidth();
5509  const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
5510  const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
5511  window->DC.ItemWidthStack.push_back(w_item_last);
5512  for (int i = 0; i < components-1; i++)
5513  window->DC.ItemWidthStack.push_back(w_item_one);
5514  window->DC.ItemWidth = window->DC.ItemWidthStack.back();
5515 }
5516 
5518 {
5519  ImGuiWindow* window = GetCurrentWindow();
5520  window->DC.ItemWidthStack.pop_back();
5521  window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
5522 }
5523 
5525 {
5526  ImGuiWindow* window = GetCurrentWindowRead();
5527  float w = window->DC.ItemWidth;
5528  if (w < 0.0f)
5529  {
5530  // 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.
5531  float width_to_right_edge = GetContentRegionAvail().x;
5532  w = ImMax(1.0f, width_to_right_edge + w);
5533  }
5534  w = (float)(int)w;
5535  return w;
5536 }
5537 
5539 {
5540  ImGuiContext& g = *GImGui;
5541  IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
5542  IM_ASSERT(font->Scale > 0.0f);
5543  g.Font = font;
5545  g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
5546 
5547  ImFontAtlas* atlas = g.Font->ContainerAtlas;
5551 }
5552 
5554 {
5555  ImGuiContext& g = *GImGui;
5556  if (!font)
5557  font = GetDefaultFont();
5558  SetCurrentFont(font);
5559  g.FontStack.push_back(font);
5561 }
5562 
5564 {
5565  ImGuiContext& g = *GImGui;
5567  g.FontStack.pop_back();
5569 }
5570 
5571 void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
5572 {
5573  ImGuiWindow* window = GetCurrentWindow();
5574  if (enabled)
5575  window->DC.ItemFlags |= option;
5576  else
5577  window->DC.ItemFlags &= ~option;
5578  window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5579 }
5580 
5582 {
5583  ImGuiWindow* window = GetCurrentWindow();
5584  window->DC.ItemFlagsStack.pop_back();
5585  window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
5586 }
5587 
5588 // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
5589 void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
5590 {
5591  PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus);
5592 }
5593 
5595 {
5596  PopItemFlag();
5597 }
5598 
5599 void ImGui::PushButtonRepeat(bool repeat)
5600 {
5602 }
5603 
5605 {
5606  PopItemFlag();
5607 }
5608 
5609 void ImGui::PushTextWrapPos(float wrap_pos_x)
5610 {
5611  ImGuiWindow* window = GetCurrentWindow();
5612  window->DC.TextWrapPos = wrap_pos_x;
5613  window->DC.TextWrapPosStack.push_back(wrap_pos_x);
5614 }
5615 
5617 {
5618  ImGuiWindow* window = GetCurrentWindow();
5619  window->DC.TextWrapPosStack.pop_back();
5620  window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back();
5621 }
5622 
5623 // FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32
5625 {
5626  ImGuiContext& g = *GImGui;
5627  ImGuiColorMod backup;
5628  backup.Col = idx;
5629  backup.BackupValue = g.Style.Colors[idx];
5630  g.ColorModifiers.push_back(backup);
5631  g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
5632 }
5633 
5635 {
5636  ImGuiContext& g = *GImGui;
5637  ImGuiColorMod backup;
5638  backup.Col = idx;
5639  backup.BackupValue = g.Style.Colors[idx];
5640  g.ColorModifiers.push_back(backup);
5641  g.Style.Colors[idx] = col;
5642 }
5643 
5644 void ImGui::PopStyleColor(int count)
5645 {
5646  ImGuiContext& g = *GImGui;
5647  while (count > 0)
5648  {
5649  ImGuiColorMod& backup = g.ColorModifiers.back();
5650  g.Style.Colors[backup.Col] = backup.BackupValue;
5652  count--;
5653  }
5654 }
5655 
5657 {
5661  void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
5662 };
5663 
5665 {
5666  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
5667  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding
5668  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding
5669  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize
5670  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize
5671  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign
5672  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding
5673  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize
5674  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding
5675  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize
5676  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding
5677  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding
5678  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize
5679  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
5680  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
5681  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
5682  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
5683  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
5684  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
5685  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
5686  { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
5687  { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
5688 };
5689 
5691 {
5692  IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
5693  IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
5694  return &GStyleVarInfo[idx];
5695 }
5696 
5698 {
5699  const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
5700  if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
5701  {
5702  ImGuiContext& g = *GImGui;
5703  float* pvar = (float*)var_info->GetVarPtr(&g.Style);
5704  g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
5705  *pvar = val;
5706  return;
5707  }
5708  IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.
5709 }
5710 
5712 {
5713  const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
5714  if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
5715  {
5716  ImGuiContext& g = *GImGui;
5717  ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
5718  g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
5719  *pvar = val;
5720  return;
5721  }
5722  IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.
5723 }
5724 
5725 void ImGui::PopStyleVar(int count)
5726 {
5727  ImGuiContext& g = *GImGui;
5728  while (count > 0)
5729  {
5730  // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
5731  ImGuiStyleMod& backup = g.StyleModifiers.back();
5732  const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
5733  void* data = info->GetVarPtr(&g.Style);
5734  if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
5735  else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
5737  count--;
5738  }
5739 }
5740 
5742 {
5743  // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
5744  switch (idx)
5745  {
5746  case ImGuiCol_Text: return "Text";
5747  case ImGuiCol_TextDisabled: return "TextDisabled";
5748  case ImGuiCol_WindowBg: return "WindowBg";
5749  case ImGuiCol_ChildBg: return "ChildBg";
5750  case ImGuiCol_PopupBg: return "PopupBg";
5751  case ImGuiCol_Border: return "Border";
5752  case ImGuiCol_BorderShadow: return "BorderShadow";
5753  case ImGuiCol_FrameBg: return "FrameBg";
5754  case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
5755  case ImGuiCol_FrameBgActive: return "FrameBgActive";
5756  case ImGuiCol_TitleBg: return "TitleBg";
5757  case ImGuiCol_TitleBgActive: return "TitleBgActive";
5758  case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
5759  case ImGuiCol_MenuBarBg: return "MenuBarBg";
5760  case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
5761  case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
5762  case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
5763  case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
5764  case ImGuiCol_CheckMark: return "CheckMark";
5765  case ImGuiCol_SliderGrab: return "SliderGrab";
5766  case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
5767  case ImGuiCol_Button: return "Button";
5768  case ImGuiCol_ButtonHovered: return "ButtonHovered";
5769  case ImGuiCol_ButtonActive: return "ButtonActive";
5770  case ImGuiCol_Header: return "Header";
5771  case ImGuiCol_HeaderHovered: return "HeaderHovered";
5772  case ImGuiCol_HeaderActive: return "HeaderActive";
5773  case ImGuiCol_Separator: return "Separator";
5774  case ImGuiCol_SeparatorHovered: return "SeparatorHovered";
5775  case ImGuiCol_SeparatorActive: return "SeparatorActive";
5776  case ImGuiCol_ResizeGrip: return "ResizeGrip";
5777  case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
5778  case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
5779  case ImGuiCol_Tab: return "Tab";
5780  case ImGuiCol_TabHovered: return "TabHovered";
5781  case ImGuiCol_TabActive: return "TabActive";
5782  case ImGuiCol_TabUnfocused: return "TabUnfocused";
5783  case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
5784  case ImGuiCol_PlotLines: return "PlotLines";
5785  case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
5786  case ImGuiCol_PlotHistogram: return "PlotHistogram";
5787  case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
5788  case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
5789  case ImGuiCol_DragDropTarget: return "DragDropTarget";
5790  case ImGuiCol_NavHighlight: return "NavHighlight";
5791  case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
5792  case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
5793  case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
5794  }
5795  IM_ASSERT(0);
5796  return "Unknown";
5797 }
5798 
5799 bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
5800 {
5801  if (window->RootWindow == potential_parent)
5802  return true;
5803  while (window != NULL)
5804  {
5805  if (window == potential_parent)
5806  return true;
5807  window = window->ParentWindow;
5808  }
5809  return false;
5810 }
5811 
5813 {
5814  IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
5815  ImGuiContext& g = *GImGui;
5816 
5817  if (flags & ImGuiHoveredFlags_AnyWindow)
5818  {
5819  if (g.HoveredWindow == NULL)
5820  return false;
5821  }
5822  else
5823  {
5825  {
5828  return false;
5829  break;
5832  return false;
5833  break;
5835  if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow))
5836  return false;
5837  break;
5838  default:
5839  if (g.HoveredWindow != g.CurrentWindow)
5840  return false;
5841  break;
5842  }
5843  }
5844 
5846  return false;
5848  if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId)
5849  return false;
5850  return true;
5851 }
5852 
5854 {
5855  ImGuiContext& g = *GImGui;
5856 
5857  if (flags & ImGuiFocusedFlags_AnyWindow)
5858  return g.NavWindow != NULL;
5859 
5860  IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End()
5862  {
5864  return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
5866  return g.NavWindow == g.CurrentWindow->RootWindow;
5869  default:
5870  return g.NavWindow == g.CurrentWindow;
5871  }
5872 }
5873 
5874 // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
5875 // Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly.
5876 // If you want a window to never be focused, you may use the e.g. NoInputs flag.
5878 {
5879  return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
5880 }
5881 
5883 {
5884  ImGuiWindow* window = GImGui->CurrentWindow;
5885  return window->Size.x;
5886 }
5887 
5889 {
5890  ImGuiWindow* window = GImGui->CurrentWindow;
5891  return window->Size.y;
5892 }
5893 
5895 {
5896  ImGuiContext& g = *GImGui;
5897  ImGuiWindow* window = g.CurrentWindow;
5898  return window->Pos;
5899 }
5900 
5901 void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
5902 {
5903  window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
5904  window->Scroll.x = new_scroll_x;
5905  window->DC.CursorMaxPos.x -= window->Scroll.x;
5906 }
5907 
5908 void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
5909 {
5910  window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
5911  window->Scroll.y = new_scroll_y;
5912  window->DC.CursorMaxPos.y -= window->Scroll.y;
5913 }
5914 
5915 static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
5916 {
5917  // Test condition (NB: bit 0 is always true) and clear flags for next time
5918  if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
5919  return;
5920 
5921  IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
5923  window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
5924 
5925  // Set
5926  const ImVec2 old_pos = window->Pos;
5927  window->Pos = ImFloor(pos);
5928  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
5929  window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
5930 }
5931 
5932 void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
5933 {
5934  ImGuiWindow* window = GetCurrentWindowRead();
5935  SetWindowPos(window, pos, cond);
5936 }
5937 
5938 void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond)
5939 {
5940  if (ImGuiWindow* window = FindWindowByName(name))
5941  SetWindowPos(window, pos, cond);
5942 }
5943 
5945 {
5946  ImGuiWindow* window = GetCurrentWindowRead();
5947  return window->Size;
5948 }
5949 
5950 static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)
5951 {
5952  // Test condition (NB: bit 0 is always true) and clear flags for next time
5953  if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
5954  return;
5955 
5956  IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
5958 
5959  // Set
5960  if (size.x > 0.0f)
5961  {
5962  window->AutoFitFramesX = 0;
5963  window->SizeFull.x = ImFloor(size.x);
5964  }
5965  else
5966  {
5967  window->AutoFitFramesX = 2;
5968  window->AutoFitOnlyGrows = false;
5969  }
5970  if (size.y > 0.0f)
5971  {
5972  window->AutoFitFramesY = 0;
5973  window->SizeFull.y = ImFloor(size.y);
5974  }
5975  else
5976  {
5977  window->AutoFitFramesY = 2;
5978  window->AutoFitOnlyGrows = false;
5979  }
5980 }
5981 
5982 void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond)
5983 {
5984  SetWindowSize(GImGui->CurrentWindow, size, cond);
5985 }
5986 
5987 void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond)
5988 {
5989  if (ImGuiWindow* window = FindWindowByName(name))
5990  SetWindowSize(window, size, cond);
5991 }
5992 
5993 static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)
5994 {
5995  // Test condition (NB: bit 0 is always true) and clear flags for next time
5996  if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
5997  return;
5999 
6000  // Set
6001  window->Collapsed = collapsed;
6002 }
6003 
6004 void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
6005 {
6006  SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
6007 }
6008 
6010 {
6011  ImGuiWindow* window = GetCurrentWindowRead();
6012  return window->Collapsed;
6013 }
6014 
6016 {
6017  ImGuiWindow* window = GetCurrentWindowRead();
6018  return window->Appearing;
6019 }
6020 
6021 void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
6022 {
6023  if (ImGuiWindow* window = FindWindowByName(name))
6024  SetWindowCollapsed(window, collapsed, cond);
6025 }
6026 
6028 {
6029  FocusWindow(GImGui->CurrentWindow);
6030 }
6031 
6032 void ImGui::SetWindowFocus(const char* name)
6033 {
6034  if (name)
6035  {
6036  if (ImGuiWindow* window = FindWindowByName(name))
6037  FocusWindow(window);
6038  }
6039  else
6040  {
6041  FocusWindow(NULL);
6042  }
6043 }
6044 
6045 void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
6046 {
6047  ImGuiContext& g = *GImGui;
6048  IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6049  g.NextWindowData.PosVal = pos;
6050  g.NextWindowData.PosPivotVal = pivot;
6051  g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
6052 }
6053 
6055 {
6056  ImGuiContext& g = *GImGui;
6057  IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6058  g.NextWindowData.SizeVal = size;
6059  g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
6060 }
6061 
6062 void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
6063 {
6064  ImGuiContext& g = *GImGui;
6066  g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
6067  g.NextWindowData.SizeCallback = custom_callback;
6068  g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
6069 }
6070 
6072 {
6073  ImGuiContext& g = *GImGui;
6074  g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
6076 }
6077 
6078 void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
6079 {
6080  ImGuiContext& g = *GImGui;
6081  IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6082  g.NextWindowData.CollapsedVal = collapsed;
6083  g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
6084 }
6085 
6087 {
6088  ImGuiContext& g = *GImGui;
6089  g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
6090 }
6091 
6093 {
6094  ImGuiContext& g = *GImGui;
6095  g.NextWindowData.BgAlphaVal = alpha;
6096  g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
6097 }
6098 
6099 // In window space (not screen space!)
6101 {
6102  ImGuiWindow* window = GetCurrentWindowRead();
6103  ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
6104  if (window->DC.ColumnsSet)
6105  mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x;
6106  return mx;
6107 }
6108 
6110 {
6111  ImGuiWindow* window = GetCurrentWindowRead();
6112  return GetContentRegionMax() - (window->DC.CursorPos - window->Pos);
6113 }
6114 
6116 {
6117  return GetContentRegionAvail().x;
6118 }
6119 
6120 // In window space (not screen space!)
6122 {
6123  ImGuiWindow* window = GetCurrentWindowRead();
6124  return window->ContentsRegionRect.Min - window->Pos;
6125 }
6126 
6128 {
6129  ImGuiWindow* window = GetCurrentWindowRead();
6130  return window->ContentsRegionRect.Max - window->Pos;
6131 }
6132 
6134 {
6135  ImGuiWindow* window = GetCurrentWindowRead();
6136  return window->ContentsRegionRect.GetWidth();
6137 }
6138 
6140 {
6141  ImGuiContext& g = *GImGui;
6142  return g.FontSize;
6143 }
6144 
6146 {
6147  ImGuiContext& g = *GImGui;
6148  return g.FontSize + g.Style.ItemSpacing.y;
6149 }
6150 
6152 {
6153  ImGuiContext& g = *GImGui;
6154  return g.FontSize + g.Style.FramePadding.y * 2.0f;
6155 }
6156 
6158 {
6159  ImGuiContext& g = *GImGui;
6160  return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
6161 }
6162 
6164 {
6165  ImGuiWindow* window = GetCurrentWindow();
6166  return window->DrawList;
6167 }
6168 
6170 {
6171  return GImGui->Font;
6172 }
6173 
6175 {
6176  return GImGui->FontSize;
6177 }
6178 
6180 {
6181  return GImGui->DrawListSharedData.TexUvWhitePixel;
6182 }
6183 
6184 void ImGui::SetWindowFontScale(float scale)
6185 {
6186  ImGuiContext& g = *GImGui;
6187  ImGuiWindow* window = GetCurrentWindow();
6188  window->FontWindowScale = scale;
6190 }
6191 
6192 // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
6193 // Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'.
6195 {
6196  ImGuiWindow* window = GetCurrentWindowRead();
6197  return window->DC.CursorPos - window->Pos + window->Scroll;
6198 }
6199 
6201 {
6202  ImGuiWindow* window = GetCurrentWindowRead();
6203  return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
6204 }
6205 
6207 {
6208  ImGuiWindow* window = GetCurrentWindowRead();
6209  return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
6210 }
6211 
6212 void ImGui::SetCursorPos(const ImVec2& local_pos)
6213 {
6214  ImGuiWindow* window = GetCurrentWindow();
6215  window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
6216  window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6217 }
6218 
6220 {
6221  ImGuiWindow* window = GetCurrentWindow();
6222  window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
6223  window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
6224 }
6225 
6227 {
6228  ImGuiWindow* window = GetCurrentWindow();
6229  window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
6230  window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
6231 }
6232 
6234 {
6235  ImGuiWindow* window = GetCurrentWindowRead();
6236  return window->DC.CursorStartPos - window->Pos;
6237 }
6238 
6240 {
6241  ImGuiWindow* window = GetCurrentWindowRead();
6242  return window->DC.CursorPos;
6243 }
6244 
6246 {
6247  ImGuiWindow* window = GetCurrentWindow();
6248  window->DC.CursorPos = pos;
6249  window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6250 }
6251 
6253 {
6254  return GImGui->CurrentWindow->Scroll.x;
6255 }
6256 
6258 {
6259  return GImGui->CurrentWindow->Scroll.y;
6260 }
6261 
6263 {
6264  return GetWindowScrollMaxX(GImGui->CurrentWindow);
6265 }
6266 
6268 {
6269  return GetWindowScrollMaxY(GImGui->CurrentWindow);
6270 }
6271 
6272 void ImGui::SetScrollX(float scroll_x)
6273 {
6274  ImGuiWindow* window = GetCurrentWindow();
6275  window->ScrollTarget.x = scroll_x;
6276  window->ScrollTargetCenterRatio.x = 0.0f;
6277 }
6278 
6279 void ImGui::SetScrollY(float scroll_y)
6280 {
6281  ImGuiWindow* window = GetCurrentWindow();
6282  window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY
6283  window->ScrollTargetCenterRatio.y = 0.0f;
6284 }
6285 
6286 void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
6287 {
6288  // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
6289  ImGuiWindow* window = GetCurrentWindow();
6290  IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
6291  window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y);
6292  window->ScrollTargetCenterRatio.y = center_y_ratio;
6293 }
6294 
6295 // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
6296 void ImGui::SetScrollHereY(float center_y_ratio)
6297 {
6298  ImGuiWindow* window = GetCurrentWindow();
6299  float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space
6300  target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line.
6301  SetScrollFromPosY(target_y, center_y_ratio);
6302 }
6303 
6305 {
6306  ImGuiContext& g = *GImGui;
6307  g.NavNextActivateId = id;
6308 }
6309 
6311 {
6312  IM_ASSERT(offset >= -1); // -1 is allowed but not below
6313  ImGuiWindow* window = GetCurrentWindow();
6314  window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
6315  window->FocusIdxTabRequestNext = INT_MAX;
6316 }
6317 
6319 {
6320  ImGuiContext& g = *GImGui;
6321  ImGuiWindow* window = g.CurrentWindow;
6322  if (!window->Appearing)
6323  return;
6324  if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent)
6325  {
6326  g.NavInitRequest = false;
6330  if (!IsItemVisible())
6331  SetScrollHereY();
6332  }
6333 }
6334 
6336 {
6337  ImGuiWindow* window = GetCurrentWindow();
6338  window->DC.StateStorage = tree ? tree : &window->StateStorage;
6339 }
6340 
6342 {
6343  ImGuiWindow* window = GetCurrentWindowRead();
6344  return window->DC.StateStorage;
6345 }
6346 
6347 void ImGui::PushID(const char* str_id)
6348 {
6349  ImGuiWindow* window = GetCurrentWindowRead();
6350  window->IDStack.push_back(window->GetIDNoKeepAlive(str_id));
6351 }
6352 
6353 void ImGui::PushID(const char* str_id_begin, const char* str_id_end)
6354 {
6355  ImGuiWindow* window = GetCurrentWindowRead();
6356  window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end));
6357 }
6358 
6359 void ImGui::PushID(const void* ptr_id)
6360 {
6361  ImGuiWindow* window = GetCurrentWindowRead();
6362  window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6363 }
6364 
6365 void ImGui::PushID(int int_id)
6366 {
6367  const void* ptr_id = (void*)(intptr_t)int_id;
6368  ImGuiWindow* window = GetCurrentWindowRead();
6369  window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6370 }
6371 
6373 {
6374  ImGuiWindow* window = GetCurrentWindowRead();
6375  window->IDStack.pop_back();
6376 }
6377 
6378 ImGuiID ImGui::GetID(const char* str_id)
6379 {
6380  return GImGui->CurrentWindow->GetID(str_id);
6381 }
6382 
6383 ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)
6384 {
6385  return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end);
6386 }
6387 
6388 ImGuiID ImGui::GetID(const void* ptr_id)
6389 {
6390  return GImGui->CurrentWindow->GetID(ptr_id);
6391 }
6392 
6393 bool ImGui::IsRectVisible(const ImVec2& size)
6394 {
6395  ImGuiWindow* window = GetCurrentWindowRead();
6396  return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
6397 }
6398 
6399 bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
6400 {
6401  ImGuiWindow* window = GetCurrentWindowRead();
6402  return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
6403 }
6404 
6405 // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
6407 {
6408  ImGuiContext& g = *GImGui;
6409  ImGuiWindow* window = GetCurrentWindow();
6410 
6411  window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
6412  ImGuiGroupData& group_data = window->DC.GroupStack.back();
6413  group_data.BackupCursorPos = window->DC.CursorPos;
6414  group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
6415  group_data.BackupIndent = window->DC.Indent;
6416  group_data.BackupGroupOffset = window->DC.GroupOffset;
6417  group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
6419  group_data.BackupLogLinePosY = window->DC.LogLinePosY;
6420  group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
6422  group_data.AdvanceCursor = true;
6423 
6424  window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
6425  window->DC.Indent = window->DC.GroupOffset;
6426  window->DC.CursorMaxPos = window->DC.CursorPos;
6427  window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
6428  window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6429 }
6430 
6432 {
6433  ImGuiContext& g = *GImGui;
6434  ImGuiWindow* window = GetCurrentWindow();
6435  IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
6436 
6437  ImGuiGroupData& group_data = window->DC.GroupStack.back();
6438 
6439  ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
6440  group_bb.Max = ImMax(group_bb.Min, group_bb.Max);
6441 
6442  window->DC.CursorPos = group_data.BackupCursorPos;
6443  window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
6444  window->DC.Indent = group_data.BackupIndent;
6445  window->DC.GroupOffset = group_data.BackupGroupOffset;
6446  window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
6447  window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
6448  window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6449 
6450  if (group_data.AdvanceCursor)
6451  {
6452  window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
6453  ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset);
6454  ItemAdd(group_bb, 0);
6455  }
6456 
6457  // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
6458  // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
6459  // (and if you grep for LastItemId you'll notice it is only used in that context.
6460  if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
6461  window->DC.LastItemId = g.ActiveId;
6462  else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
6463  window->DC.LastItemId = g.ActiveIdPreviousFrame;
6464  window->DC.LastItemRect = group_bb;
6465 
6466  window->DC.GroupStack.pop_back();
6467 
6468  //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
6469 }
6470 
6471 // Gets back to previous line and continue with horizontal layout
6472 // pos_x == 0 : follow right after previous item
6473 // pos_x != 0 : align to specified x position (relative to window/group left)
6474 // spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0
6475 // spacing_w >= 0 : enforce spacing amount
6476 void ImGui::SameLine(float pos_x, float spacing_w)
6477 {
6478  ImGuiWindow* window = GetCurrentWindow();
6479  if (window->SkipItems)
6480  return;
6481 
6482  ImGuiContext& g = *GImGui;
6483  if (pos_x != 0.0f)
6484  {
6485  if (spacing_w < 0.0f) spacing_w = 0.0f;
6486  window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
6487  window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6488  }
6489  else
6490  {
6491  if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;
6492  window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
6493  window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6494  }
6495  window->DC.CurrentLineSize = window->DC.PrevLineSize;
6497 }
6498 
6499 void ImGui::Indent(float indent_w)
6500 {
6501  ImGuiContext& g = *GImGui;
6502  ImGuiWindow* window = GetCurrentWindow();
6503  window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6504  window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6505 }
6506 
6507 void ImGui::Unindent(float indent_w)
6508 {
6509  ImGuiContext& g = *GImGui;
6510  ImGuiWindow* window = GetCurrentWindow();
6511  window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6512  window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6513 }
6514 
6515 //-----------------------------------------------------------------------------
6516 // [SECTION] TOOLTIPS
6517 //-----------------------------------------------------------------------------
6518 
6520 {
6521  ImGuiContext& g = *GImGui;
6523  {
6524  // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor)
6525  // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor.
6526  // Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do.
6527  //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
6528  ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale);
6529  SetNextWindowPos(tooltip_pos);
6531  //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
6532  BeginTooltipEx(0, true);
6533  }
6534  else
6535  {
6536  BeginTooltipEx(0, false);
6537  }
6538 }
6539 
6540 // Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first.
6541 void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip)
6542 {
6543  ImGuiContext& g = *GImGui;
6544  char window_name[16];
6545  ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
6546  if (override_previous_tooltip)
6547  if (ImGuiWindow* window = FindWindowByName(window_name))
6548  if (window->Active)
6549  {
6550  // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
6551  window->Hidden = true;
6552  window->HiddenFramesRegular = 1;
6553  ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
6554  }
6556  Begin(window_name, NULL, flags | extra_flags);
6557 }
6558 
6560 {
6561  IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls
6562  End();
6563 }
6564 
6565 void ImGui::SetTooltipV(const char* fmt, va_list args)
6566 {
6567  ImGuiContext& g = *GImGui;
6569  BeginTooltip();
6570  else
6571  BeginTooltipEx(0, true);
6572  TextV(fmt, args);
6573  EndTooltip();
6574 }
6575 
6576 void ImGui::SetTooltip(const char* fmt, ...)
6577 {
6578  va_list args;
6579  va_start(args, fmt);
6580  SetTooltipV(fmt, args);
6581  va_end(args);
6582 }
6583 
6584 //-----------------------------------------------------------------------------
6585 // [SECTION] POPUPS
6586 //-----------------------------------------------------------------------------
6587 
6589 {
6590  ImGuiContext& g = *GImGui;
6591  return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
6592 }
6593 
6594 bool ImGui::IsPopupOpen(const char* str_id)
6595 {
6596  ImGuiContext& g = *GImGui;
6597  return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
6598 }
6599 
6601 {
6602  ImGuiContext& g = *GImGui;
6603  for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)
6604  if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
6605  if (popup->Flags & ImGuiWindowFlags_Modal)
6606  return popup;
6607  return NULL;
6608 }
6609 
6610 void ImGui::OpenPopup(const char* str_id)
6611 {
6612  ImGuiContext& g = *GImGui;
6613  OpenPopupEx(g.CurrentWindow->GetID(str_id));
6614 }
6615 
6616 // Mark popup as open (toggle toward open state).
6617 // Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
6618 // Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
6619 // One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
6621 {
6622  ImGuiContext& g = *GImGui;
6623  ImGuiWindow* parent_window = g.CurrentWindow;
6624  int current_stack_size = g.BeginPopupStack.Size;
6625  ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
6626  popup_ref.PopupId = id;
6627  popup_ref.Window = NULL;
6628  popup_ref.ParentWindow = parent_window;
6629  popup_ref.OpenFrameCount = g.FrameCount;
6630  popup_ref.OpenParentId = parent_window->IDStack.back();
6631  popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
6632  popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
6633 
6634  //IMGUI_DEBUG_LOG("OpenPopupEx(0x%08X)\n", g.FrameCount, id);
6635  if (g.OpenPopupStack.Size < current_stack_size + 1)
6636  {
6637  g.OpenPopupStack.push_back(popup_ref);
6638  }
6639  else
6640  {
6641  // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui
6642  // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing
6643  // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand.
6644  if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1)
6645  {
6646  g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
6647  }
6648  else
6649  {
6650  // Close child popups if any, then flag popup for open/reopen
6651  g.OpenPopupStack.resize(current_stack_size + 1);
6652  g.OpenPopupStack[current_stack_size] = popup_ref;
6653  }
6654 
6655  // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
6656  // This is equivalent to what ClosePopupToLevel() does.
6657  //if (g.OpenPopupStack[current_stack_size].PopupId == id)
6658  // FocusWindow(parent_window);
6659  }
6660 }
6661 
6662 bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button)
6663 {
6664  ImGuiWindow* window = GImGui->CurrentWindow;
6666  {
6667  ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
6668  IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
6669  OpenPopupEx(id);
6670  return true;
6671  }
6672  return false;
6673 }
6674 
6676 {
6677  ImGuiContext& g = *GImGui;
6678  if (g.OpenPopupStack.empty())
6679  return;
6680 
6681  // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
6682  // Don't close our own child popup windows.
6683  int popup_count_to_keep = 0;
6684  if (ref_window)
6685  {
6686  // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
6687  for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
6688  {
6689  ImGuiPopupRef& popup = g.OpenPopupStack[popup_count_to_keep];
6690  if (!popup.Window)
6691  continue;
6692  IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
6694  continue;
6695 
6696  // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow)
6697  bool popup_or_descendent_has_focus = false;
6698  for (int m = popup_count_to_keep; m < g.OpenPopupStack.Size && !popup_or_descendent_has_focus; m++)
6699  if (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow)
6700  popup_or_descendent_has_focus = true;
6701  if (!popup_or_descendent_has_focus)
6702  break;
6703  }
6704  }
6705  if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
6706  {
6707  //IMGUI_DEBUG_LOG("ClosePopupsOverWindow(%s) -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
6708  ClosePopupToLevel(popup_count_to_keep, false);
6709  }
6710 }
6711 
6712 void ImGui::ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
6713 {
6714  IM_ASSERT(remaining >= 0);
6715  ImGuiContext& g = *GImGui;
6716  ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow;
6717  g.OpenPopupStack.resize(remaining);
6718 
6719  // FIXME: This code is faulty and we may want to eventually to replace or remove the 'apply_focus_to_window_under=true' path completely.
6720  // Instead of using g.OpenPopupStack[remaining-1].Window etc. we should find the highest root window that is behind the popups we are closing.
6721  // The current code will set focus to the parent of the popup window which is incorrect.
6722  // It rarely manifested until now because UpdateMouseMovingWindow() would call FocusWindow() again on the clicked window,
6723  // leading to a chain of focusing A (clicked window) then B (parent window of the popup) then A again.
6724  // However if the clicked window has the _NoMove flag set we would be left with B focused.
6725  // For now, we have disabled this path when called from ClosePopupsOverWindow() because the users of ClosePopupsOverWindow() don't need to alter focus anyway,
6726  // but we should inspect and fix this properly.
6727  if (apply_focus_to_window_under)
6728  {
6729  if (g.NavLayer == 0)
6730  focus_window = NavRestoreLastChildNavWindow(focus_window);
6731  FocusWindow(focus_window);
6732  }
6733 }
6734 
6735 // Close the popup we have begin-ed into.
6737 {
6738  ImGuiContext& g = *GImGui;
6739  int popup_idx = g.BeginPopupStack.Size - 1;
6740  if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
6741  return;
6742  while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu))
6743  popup_idx--;
6744  ClosePopupToLevel(popup_idx, true);
6745 
6746  // A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
6747  // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
6748  // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
6749  if (ImGuiWindow* window = g.NavWindow)
6750  window->DC.NavHideHighlightOneFrame = true;
6751 }
6752 
6754 {
6755  ImGuiContext& g = *GImGui;
6756  if (!IsPopupOpen(id))
6757  {
6758  g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6759  return false;
6760  }
6761 
6762  char name[20];
6763  if (extra_flags & ImGuiWindowFlags_ChildMenu)
6764  ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
6765  else
6766  ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
6767 
6768  bool is_open = Begin(name, NULL, extra_flags | ImGuiWindowFlags_Popup);
6769  if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
6770  EndPopup();
6771 
6772  return is_open;
6773 }
6774 
6775 bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
6776 {
6777  ImGuiContext& g = *GImGui;
6778  if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
6779  {
6780  g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6781  return false;
6782  }
6784  return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags);
6785 }
6786 
6787 // If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
6788 // Note that popup visibility status is owned by imgui (and manipulated with e.g. OpenPopup) so the actual value of *p_open is meaningless here.
6789 bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags)
6790 {
6791  ImGuiContext& g = *GImGui;
6792  ImGuiWindow* window = g.CurrentWindow;
6793  const ImGuiID id = window->GetID(name);
6794  if (!IsPopupOpen(id))
6795  {
6796  g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6797  return false;
6798  }
6799 
6800  // Center modal windows by default
6801  // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
6802  if (g.NextWindowData.PosCond == 0)
6804 
6806  const bool is_open = Begin(name, p_open, flags);
6807  if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
6808  {
6809  EndPopup();
6810  if (is_open)
6812  return false;
6813  }
6814  return is_open;
6815 }
6816 
6818 {
6819  ImGuiContext& g = *GImGui; (void)g;
6820  IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
6822 
6823  // Make all menus and popups wrap around for now, may need to expose that policy.
6825 
6826  End();
6827 }
6828 
6829 // This is a helper to handle the simplest case of associating one named popup to one given widget.
6830 // You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
6831 // You can pass a NULL str_id to use the identifier of the last item.
6832 bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button)
6833 {
6834  ImGuiWindow* window = GImGui->CurrentWindow;
6835  ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
6836  IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
6838  OpenPopupEx(id);
6840 }
6841 
6842 bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items)
6843 {
6844  if (!str_id)
6845  str_id = "window_context";
6846  ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
6848  if (also_over_items || !IsAnyItemHovered())
6849  OpenPopupEx(id);
6851 }
6852 
6853 bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
6854 {
6855  if (!str_id)
6856  str_id = "void_context";
6857  ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
6859  OpenPopupEx(id);
6861 }
6862 
6864 {
6865  ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding;
6866  ImRect r_screen = GetViewportRect();
6867  r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
6868  return r_screen;
6869 }
6870 
6871 // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.)
6872 // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it.
6873 ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
6874 {
6875  ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
6876  //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255));
6877  //GImGui->OverlayDrawList.AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255));
6878 
6879  // Combo Box policy (we want a connecting edge)
6880  if (policy == ImGuiPopupPositionPolicy_ComboBox)
6881  {
6882  const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
6883  for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
6884  {
6885  const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
6886  if (n != -1 && dir == *last_dir) // Already tried this direction?
6887  continue;
6888  ImVec2 pos;
6889  if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default)
6890  if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right
6891  if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left
6892  if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left
6893  if (!r_outer.Contains(ImRect(pos, pos + size)))
6894  continue;
6895  *last_dir = dir;
6896  return pos;
6897  }
6898  }
6899 
6900  // Default popup policy
6901  const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
6902  for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
6903  {
6904  const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
6905  if (n != -1 && dir == *last_dir) // Already tried this direction?
6906  continue;
6907  float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
6908  float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
6909  if (avail_w < size.x || avail_h < size.y)
6910  continue;
6911  ImVec2 pos;
6912  pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
6913  pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
6914  *last_dir = dir;
6915  return pos;
6916  }
6917 
6918  // Fallback, try to keep within display
6919  *last_dir = ImGuiDir_None;
6920  ImVec2 pos = ref_pos;
6921  pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
6922  pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
6923  return pos;
6924 }
6925 
6927 {
6928  ImGuiContext& g = *GImGui;
6929 
6930  ImRect r_outer = GetWindowAllowedExtentRect(window);
6931  if (window->Flags & ImGuiWindowFlags_ChildMenu)
6932  {
6933  // Child menus typically request _any_ position within the parent menu item, and then our FindBestWindowPosForPopup() function will move the new menu outside the parent bounds.
6934  // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.
6935  IM_ASSERT(g.CurrentWindow == window);
6936  ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2];
6937  float horizontal_overlap = g.Style.ItemSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x).
6938  ImRect r_avoid;
6939  if (parent_window->DC.MenuBarAppending)
6940  r_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight());
6941  else
6942  r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
6943  return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
6944  }
6945  if (window->Flags & ImGuiWindowFlags_Popup)
6946  {
6947  ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
6948  return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
6949  }
6950  if (window->Flags & ImGuiWindowFlags_Tooltip)
6951  {
6952  // Position tooltip (always follows mouse)
6953  float sc = g.Style.MouseCursorScale;
6954  ImVec2 ref_pos = NavCalcPreferredRefPos();
6955  ImRect r_avoid;
6957  r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
6958  else
6959  r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
6960  ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
6961  if (window->AutoPosLastDirection == ImGuiDir_None)
6962  pos = ref_pos + ImVec2(2, 2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
6963  return pos;
6964  }
6965  IM_ASSERT(0);
6966  return window->Pos;
6967 }
6968 
6969 //-----------------------------------------------------------------------------
6970 // [SECTION] VIEWPORTS, PLATFORM WINDOWS
6971 //-----------------------------------------------------------------------------
6972 
6973 // (this section is filled in the 'viewport' and 'docking' branches)
6974 
6975 //-----------------------------------------------------------------------------
6976 // [SECTION] KEYBOARD/GAMEPAD NAVIGATION
6977 //-----------------------------------------------------------------------------
6978 
6980 {
6981  if (ImFabs(dx) > ImFabs(dy))
6982  return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
6983  return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
6984 }
6985 
6986 static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
6987 {
6988  if (a1 < b0)
6989  return a1 - b0;
6990  if (b1 < a0)
6991  return a0 - b1;
6992  return 0.0f;
6993 }
6994 
6995 static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect)
6996 {
6997  if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
6998  {
6999  r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y);
7000  r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y);
7001  }
7002  else
7003  {
7004  r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x);
7005  r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x);
7006  }
7007 }
7008 
7009 // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057
7010 static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
7011 {
7012  ImGuiContext& g = *GImGui;
7013  ImGuiWindow* window = g.CurrentWindow;
7014  if (g.NavLayer != window->DC.NavLayerCurrent)
7015  return false;
7016 
7017  const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
7018  g.NavScoringCount++;
7019 
7020  // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
7021  if (window->ParentWindow == g.NavWindow)
7022  {
7024  if (!window->ClipRect.Contains(cand))
7025  return false;
7026  cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window
7027  }
7028 
7029  // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
7030  // For example, this ensure that items in one column are not reached when moving vertically from items in another column.
7032 
7033  // Compute distance between boxes
7034  // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
7035  float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
7036  float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items
7037  if (dby != 0.0f && dbx != 0.0f)
7038  dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
7039  float dist_box = ImFabs(dbx) + ImFabs(dby);
7040 
7041  // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
7042  float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
7043  float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
7044  float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee)
7045 
7046  // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
7047  ImGuiDir quadrant;
7048  float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
7049  if (dbx != 0.0f || dby != 0.0f)
7050  {
7051  // For non-overlapping boxes, use distance between boxes
7052  dax = dbx;
7053  day = dby;
7054  dist_axial = dist_box;
7055  quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
7056  }
7057  else if (dcx != 0.0f || dcy != 0.0f)
7058  {
7059  // For overlapping boxes with different centers, use distance between centers
7060  dax = dcx;
7061  day = dcy;
7062  dist_axial = dist_center;
7063  quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
7064  }
7065  else
7066  {
7067  // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
7068  quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
7069  }
7070 
7071 #if IMGUI_DEBUG_NAV_SCORING
7072  char buf[128];
7073  if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max))
7074  {
7075  ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]);
7076  ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7077  draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100));
7078  draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200));
7079  draw_list->AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150));
7080  draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf);
7081  }
7082  else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
7083  {
7085  if (quadrant == g.NavMoveDir)
7086  {
7087  ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
7088  ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7089  draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200));
7090  draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf);
7091  }
7092  }
7093  #endif
7094 
7095  // Is it in the quadrant we're interesting in moving to?
7096  bool new_best = false;
7097  if (quadrant == g.NavMoveDir)
7098  {
7099  // Does it beat the current best candidate?
7100  if (dist_box < result->DistBox)
7101  {
7102  result->DistBox = dist_box;
7103  result->DistCenter = dist_center;
7104  return true;
7105  }
7106  if (dist_box == result->DistBox)
7107  {
7108  // Try using distance between center points to break ties
7109  if (dist_center < result->DistCenter)
7110  {
7111  result->DistCenter = dist_center;
7112  new_best = true;
7113  }
7114  else if (dist_center == result->DistCenter)
7115  {
7116  // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
7117  // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
7118  // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
7119  if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
7120  new_best = true;
7121  }
7122  }
7123  }
7124 
7125  // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches
7126  // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
7127  // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too.
7128  // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward.
7129  // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
7130  if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match
7131  if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
7132  if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f))
7133  {
7134  result->DistAxial = dist_axial;
7135  new_best = true;
7136  }
7137 
7138  return new_best;
7139 }
7140 
7141 // We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
7142 static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
7143 {
7144  ImGuiContext& g = *GImGui;
7145  //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
7146  // return;
7147 
7148  const ImGuiItemFlags item_flags = window->DC.ItemFlags;
7149  const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
7150 
7151  // Process Init Request
7152  if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
7153  {
7154  // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
7155  if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0)
7156  {
7157  g.NavInitResultId = id;
7158  g.NavInitResultRectRel = nav_bb_rel;
7159  }
7160  if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus))
7161  {
7162  g.NavInitRequest = false; // Found a match, clear request
7164  }
7165  }
7166 
7167  // Process Move Request (scoring for navigation)
7168  // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
7169  if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & ImGuiItemFlags_NoNav))
7170  {
7171  ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
7173  // [DEBUG] Score all items in NavWindow at all times
7174  if (!g.NavMoveRequest)
7175  g.NavMoveDir = g.NavMoveDirLast;
7176  bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest;
7177 #else
7178  bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb);
7179 #endif
7180  if (new_best)
7181  {
7182  result->ID = id;
7183  result->Window = window;
7184  result->RectRel = nav_bb_rel;
7185  }
7186 
7187  const float VISIBLE_RATIO = 0.70f;
7189  if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
7191  {
7192  result = &g.NavMoveResultLocalVisibleSet;
7193  result->ID = id;
7194  result->Window = window;
7195  result->RectRel = nav_bb_rel;
7196  }
7197  }
7198 
7199  // Update window-relative bounding box of navigated item
7200  if (g.NavId == id)
7201  {
7202  g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
7203  g.NavLayer = window->DC.NavLayerCurrent;
7204  g.NavIdIsAlive = true;
7205  g.NavIdTabCounter = window->FocusIdxTabCounter;
7206  window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
7207  }
7208 }
7209 
7211 {
7212  ImGuiContext& g = *GImGui;
7213  return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
7214 }
7215 
7217 {
7218  ImGuiContext& g = *GImGui;
7219  g.NavMoveRequest = false;
7221 }
7222 
7223 void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags)
7224 {
7225  ImGuiContext& g = *GImGui;
7228  g.NavMoveDir = move_dir;
7229  g.NavMoveClipDir = clip_dir;
7231  g.NavMoveRequestFlags = move_flags;
7232  g.NavWindow->NavRectRel[g.NavLayer] = bb_rel;
7233 }
7234 
7236 {
7237  ImGuiContext& g = *GImGui;
7239  return;
7240  IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
7241  ImRect bb_rel = window->NavRectRel[0];
7242 
7243  ImGuiDir clip_dir = g.NavMoveDir;
7245  {
7246  bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
7247  if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
7248  NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7249  }
7251  {
7252  bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
7253  if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
7254  NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7255  }
7257  {
7258  bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
7259  if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
7260  NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7261  }
7263  {
7264  bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
7265  if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
7266  NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7267  }
7268 }
7269 
7271 {
7272  ImGuiWindow* parent_window = nav_window;
7273  while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
7274  parent_window = parent_window->ParentWindow;
7275  if (parent_window && parent_window != nav_window)
7276  parent_window->NavLastChildNavWindow = nav_window;
7277 }
7278 
7279 // Call when we are expected to land on Layer 0 after FocusWindow()
7281 {
7282  return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
7283 }
7284 
7285 static void NavRestoreLayer(ImGuiNavLayer layer)
7286 {
7287  ImGuiContext& g = *GImGui;
7288  g.NavLayer = layer;
7289  if (layer == 0)
7291  if (layer == 0 && g.NavWindow->NavLastIds[0] != 0)
7293  else
7295 }
7296 
7298 {
7299  ImGuiContext& g = *GImGui;
7301  if (g.NavAnyRequest)
7302  IM_ASSERT(g.NavWindow != NULL);
7303 }
7304 
7305 // This needs to be called before we submit any widget (aka in or before Begin)
7306 void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
7307 {
7308  ImGuiContext& g = *GImGui;
7309  IM_ASSERT(window == g.NavWindow);
7310  bool init_for_nav = false;
7311  if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
7312  if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
7313  init_for_nav = true;
7314  if (init_for_nav)
7315  {
7316  SetNavID(0, g.NavLayer);
7317  g.NavInitRequest = true;
7318  g.NavInitRequestFromMove = false;
7319  g.NavInitResultId = 0;
7322  }
7323  else
7324  {
7325  g.NavId = window->NavLastIds[0];
7326  }
7327 }
7328 
7330 {
7331  ImGuiContext& g = *GImGui;
7333  {
7334  // Mouse (we need a fallback in case the mouse becomes invalid after being used)
7335  if (IsMousePosValid(&g.IO.MousePos))
7336  return g.IO.MousePos;
7337  return g.LastValidMousePos;
7338  }
7339  else
7340  {
7341  // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
7342  const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
7343  ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
7344  ImRect visible_rect = GetViewportRect();
7345  return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta.
7346  }
7347 }
7348 
7350 {
7351  ImGuiContext& g = *GImGui;
7352  if (mode == ImGuiInputReadMode_Down)
7353  return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user)
7354 
7355  const float t = g.IO.NavInputsDownDuration[n];
7356  if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input.
7357  return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
7358  if (t < 0.0f)
7359  return 0.0f;
7360  if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input.
7361  return (t == 0.0f) ? 1.0f : 0.0f;
7362  if (mode == ImGuiInputReadMode_Repeat)
7363  return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f);
7364  if (mode == ImGuiInputReadMode_RepeatSlow)
7365  return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f);
7366  if (mode == ImGuiInputReadMode_RepeatFast)
7367  return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f);
7368  return 0.0f;
7369 }
7370 
7371 ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor)
7372 {
7373  ImVec2 delta(0.0f, 0.0f);
7374  if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
7376  if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
7378  if (dir_sources & ImGuiNavDirSourceFlags_PadLStick)
7380  if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow))
7381  delta *= slow_factor;
7382  if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast))
7383  delta *= fast_factor;
7384  return delta;
7385 }
7386 
7387 // Scroll to keep newly navigated item fully into view
7388 // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
7389 static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
7390 {
7391  ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
7392  //GetOverlayDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
7393  if (window_rect.Contains(item_rect))
7394  return;
7395 
7396  ImGuiContext& g = *GImGui;
7397  if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
7398  {
7399  window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x;
7400  window->ScrollTargetCenterRatio.x = 0.0f;
7401  }
7402  else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
7403  {
7404  window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x;
7405  window->ScrollTargetCenterRatio.x = 1.0f;
7406  }
7407  if (item_rect.Min.y < window_rect.Min.y)
7408  {
7409  window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y;
7410  window->ScrollTargetCenterRatio.y = 0.0f;
7411  }
7412  else if (item_rect.Max.y >= window_rect.Max.y)
7413  {
7414  window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y;
7415  window->ScrollTargetCenterRatio.y = 1.0f;
7416  }
7417 }
7418 
7419 static void ImGui::NavUpdate()
7420 {
7421  ImGuiContext& g = *GImGui;
7422  g.IO.WantSetMousePos = false;
7423 #if 0
7424  if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
7425 #endif
7426 
7427  // Set input source as Gamepad when buttons are pressed before we map Keyboard (some features differs when used with Gamepad vs Keyboard)
7428  bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
7429  bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
7430  if (nav_gamepad_active)
7433 
7434  // Update Keyboard->Nav inputs mapping
7435  if (nav_keyboard_active)
7436  {
7437  #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; }
7445  if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
7446  if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
7447  if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
7448  #undef NAV_MAP_KEY
7449  }
7451  for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++)
7452  g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f;
7453 
7454  // Process navigation init request (select first/default focus)
7456  {
7457  // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
7458  IM_ASSERT(g.NavWindow);
7459  if (g.NavInitRequestFromMove)
7461  else
7464  }
7465  g.NavInitRequest = false;
7466  g.NavInitRequestFromMove = false;
7467  g.NavInitResultId = 0;
7468  g.NavJustMovedToId = 0;
7469 
7470  // Process navigation move request
7471  if (g.NavMoveRequest)
7473 
7474  // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame
7476  {
7478  if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
7479  g.NavDisableHighlight = false;
7481  }
7482 
7483  // Apply application mouse position movement, after we had a chance to process move request result.
7484  if (g.NavMousePosDirty && g.NavIdIsAlive)
7485  {
7486  // Set mouse position given our knowledge of the navigated item position from last frame
7488  {
7490  {
7492  g.IO.WantSetMousePos = true;
7493  }
7494  }
7495  g.NavMousePosDirty = false;
7496  }
7497  g.NavIdIsAlive = false;
7498  g.NavJustTabbedId = 0;
7499  IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1);
7500 
7501  // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0
7502  if (g.NavWindow)
7504  if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0)
7505  g.NavWindow->NavLastChildNavWindow = NULL;
7506 
7507  // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.)
7509 
7510  // Set output flags for user application
7511  g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
7512  g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest;
7513 
7514  // Process NavCancel input (to close a popup, get back to parent, clear focus)
7516  {
7517  if (g.ActiveId != 0)
7518  {
7519  ClearActiveID();
7520  }
7522  {
7523  // Exit child window
7524  ImGuiWindow* child_window = g.NavWindow;
7525  ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
7526  IM_ASSERT(child_window->ChildId != 0);
7527  FocusWindow(parent_window);
7528  SetNavID(child_window->ChildId, 0);
7529  g.NavIdIsAlive = false;
7530  if (g.NavDisableMouseHover)
7531  g.NavMousePosDirty = true;
7532  }
7533  else if (g.OpenPopupStack.Size > 0)
7534  {
7535  // Close open popup/menu
7537  ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
7538  }
7539  else if (g.NavLayer != 0)
7540  {
7541  // Leave the "menu" layer
7543  }
7544  else
7545  {
7546  // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
7548  g.NavWindow->NavLastIds[0] = 0;
7549  g.NavId = 0;
7550  }
7551  }
7552 
7553  // Process manual activation request
7556  {
7557  bool activate_down = IsNavInputDown(ImGuiNavInput_Activate);
7558  bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed);
7559  if (g.ActiveId == 0 && activate_pressed)
7560  g.NavActivateId = g.NavId;
7561  if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
7562  g.NavActivateDownId = g.NavId;
7563  if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
7565  if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed))
7566  g.NavInputId = g.NavId;
7567  }
7569  g.NavDisableHighlight = true;
7570  if (g.NavActivateId != 0)
7572  g.NavMoveRequest = false;
7573 
7574  // Process programmatic activation request
7575  if (g.NavNextActivateId != 0)
7577  g.NavNextActivateId = 0;
7578 
7579  // Initiate directional inputs request
7580  const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags;
7582  {
7585  if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
7586  {
7591  }
7592  g.NavMoveClipDir = g.NavMoveDir;
7593  }
7594  else
7595  {
7596  // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
7597  // (Preserve g.NavMoveRequestFlags, g.NavMoveClipDir which were set by the NavMoveRequestForward() function)
7601  }
7602 
7603  // Update PageUp/PageDown scroll
7604  float nav_scoring_rect_offset_y = 0.0f;
7605  if (nav_keyboard_active)
7606  nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
7607 
7608  // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match
7609  if (g.NavMoveDir != ImGuiDir_None)
7610  {
7611  g.NavMoveRequest = true;
7612  g.NavMoveDirLast = g.NavMoveDir;
7613  }
7614  if (g.NavMoveRequest && g.NavId == 0)
7615  {
7617  g.NavInitResultId = 0;
7618  g.NavDisableHighlight = false;
7619  }
7621 
7622  // Scrolling
7624  {
7625  // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
7626  ImGuiWindow* window = g.NavWindow;
7627  const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
7628  if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
7629  {
7631  SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
7633  SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
7634  }
7635 
7636  // *Normal* Manual scroll with NavScrollXXX keys
7637  // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
7639  if (scroll_dir.x != 0.0f && window->ScrollbarX)
7640  {
7641  SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
7642  g.NavMoveFromClampedRefRect = true;
7643  }
7644  if (scroll_dir.y != 0.0f)
7645  {
7646  SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
7647  g.NavMoveFromClampedRefRect = true;
7648  }
7649  }
7650 
7651  // Reset search results
7655 
7656  // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items
7657  if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
7658  {
7659  ImGuiWindow* window = g.NavWindow;
7660  ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
7661  if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
7662  {
7663  float pad = window->CalcFontSize() * 0.5f;
7664  window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
7665  window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel);
7666  g.NavId = 0;
7667  }
7668  g.NavMoveFromClampedRefRect = false;
7669  }
7670 
7671  // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
7672  ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0);
7673  g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect();
7674  g.NavScoringRectScreen.TranslateY(nav_scoring_rect_offset_y);
7677  IM_ASSERT(!g.NavScoringRectScreen.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
7678  //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG]
7679  g.NavScoringCount = 0;
7680 #if IMGUI_DEBUG_NAV_RECTS
7681  if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList(g.NavWindow)->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG]
7682  if (g.NavWindow) { ImU32 col = (!g.NavWindow->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
7683 #endif
7684 }
7685 
7686 // Apply result from previous frame navigation directional move request
7688 {
7689  ImGuiContext& g = *GImGui;
7690  if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
7691  {
7692  // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result)
7693  if (g.NavId != 0)
7694  {
7695  g.NavDisableHighlight = false;
7696  g.NavDisableMouseHover = true;
7697  }
7698  return;
7699  }
7700 
7701  // Select which result to use
7703 
7704  // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
7707  result = &g.NavMoveResultLocalVisibleSet;
7708 
7709  // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
7711  if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
7712  result = &g.NavMoveResultOther;
7713  IM_ASSERT(g.NavWindow && result->Window);
7714 
7715  // Scroll to keep newly navigated item fully into view.
7716  if (g.NavLayer == 0)
7717  {
7718  ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
7719  NavScrollToBringItemIntoView(result->Window, rect_abs);
7720 
7721  // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate()
7722  ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false);
7723  ImVec2 delta_scroll = result->Window->Scroll - next_scroll;
7724  result->RectRel.Translate(delta_scroll);
7725 
7726  // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
7727  if (result->Window->Flags & ImGuiWindowFlags_ChildWindow)
7728  NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll));
7729  }
7730 
7731  ClearActiveID();
7732  g.NavWindow = result->Window;
7733  SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel);
7734  g.NavJustMovedToId = result->ID;
7735  g.NavMoveFromClampedRefRect = false;
7736 }
7737 
7738 static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
7739 {
7740  ImGuiContext& g = *GImGui;
7742  {
7743  ImGuiWindow* window = g.NavWindow;
7744  bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
7745  bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
7746  if ((page_up_held && !page_down_held) || (page_down_held && !page_up_held))
7747  {
7748  if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
7749  {
7750  // Fallback manual-scroll when window has no navigable item
7751  if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
7752  SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
7753  else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
7754  SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
7755  }
7756  else
7757  {
7758  const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
7759  const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
7760  float nav_scoring_rect_offset_y = 0.0f;
7761  if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
7762  {
7763  nav_scoring_rect_offset_y = -page_offset_y;
7764  g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
7767  }
7768  else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
7769  {
7770  nav_scoring_rect_offset_y = +page_offset_y;
7771  g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
7774  }
7775  return nav_scoring_rect_offset_y;
7776  }
7777  }
7778  }
7779  return 0.0f;
7780 }
7781 
7782 static int FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
7783 {
7784  ImGuiContext& g = *GImGui;
7785  for (int i = g.WindowsFocusOrder.Size-1; i >= 0; i--)
7786  if (g.WindowsFocusOrder[i] == window)
7787  return i;
7788  return -1;
7789 }
7790 
7791 static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
7792 {
7793  ImGuiContext& g = *GImGui;
7794  for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir)
7796  return g.WindowsFocusOrder[i];
7797  return NULL;
7798 }
7799 
7800 static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
7801 {
7802  ImGuiContext& g = *GImGui;
7805  return;
7806 
7807  const int i_current = FindWindowFocusIndex(g.NavWindowingTarget);
7808  ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
7809  if (!window_target)
7810  window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
7811  if (window_target) // Don't reset windowing target if there's a single window in the list
7812  g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
7813  g.NavWindowingToggleLayer = false;
7814 }
7815 
7816 // Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer)
7818 {
7819  ImGuiContext& g = *GImGui;
7820  ImGuiWindow* apply_focus_window = NULL;
7821  bool apply_toggle_layer = false;
7822 
7823  ImGuiWindow* modal_window = GetFrontMostPopupModal();
7824  if (modal_window != NULL)
7825  {
7826  g.NavWindowingTarget = NULL;
7827  return;
7828  }
7829 
7830  // Fade out
7831  if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
7832  {
7834  if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
7835  g.NavWindowingTargetAnim = NULL;
7836  }
7837 
7838  // Start CTRL-TAB or Square+L/R window selection
7839  bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
7840  bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
7841  if (start_windowing_with_gamepad || start_windowing_with_keyboard)
7842  if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
7843  {
7846  g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
7847  g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
7848  }
7849 
7850  // Gamepad update
7853  {
7854  // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
7856 
7857  // Select window to focus
7859  if (focus_change_dir != 0)
7860  {
7861  NavUpdateWindowingHighlightWindow(focus_change_dir);
7862  g.NavWindowingHighlightAlpha = 1.0f;
7863  }
7864 
7865  // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most)
7867  {
7868  g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore.
7870  apply_toggle_layer = true;
7871  else if (!g.NavWindowingToggleLayer)
7872  apply_focus_window = g.NavWindowingTarget;
7873  g.NavWindowingTarget = NULL;
7874  }
7875  }
7876 
7877  // Keyboard: Focus
7879  {
7880  // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
7882  if (IsKeyPressedMap(ImGuiKey_Tab, true))
7884  if (!g.IO.KeyCtrl)
7885  apply_focus_window = g.NavWindowingTarget;
7886  }
7887 
7888  // Keyboard: Press and Release ALT to toggle menu layer
7889  // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB
7892  apply_toggle_layer = true;
7893 
7894  // Move window
7896  {
7897  ImVec2 move_delta;
7902  if (move_delta.x != 0.0f || move_delta.y != 0.0f)
7903  {
7904  const float NAV_MOVE_SPEED = 800.0f;
7905  const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't code variable framerate very well
7906  g.NavWindowingTarget->RootWindow->Pos += move_delta * move_speed;
7907  g.NavDisableMouseHover = true;
7909  }
7910  }
7911 
7912  // Apply final focus
7913  if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
7914  {
7915  g.NavDisableHighlight = false;
7916  g.NavDisableMouseHover = true;
7917  apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
7918  ClosePopupsOverWindow(apply_focus_window);
7919  FocusWindow(apply_focus_window);
7920  if (apply_focus_window->NavLastIds[0] == 0)
7921  NavInitWindow(apply_focus_window, false);
7922 
7923  // If the window only has a menu layer, select it directly
7924  if (apply_focus_window->DC.NavLayerActiveMask == (1 << ImGuiNavLayer_Menu))
7926  }
7927  if (apply_focus_window)
7928  g.NavWindowingTarget = NULL;
7929 
7930  // Apply menu/layer toggle
7931  if (apply_toggle_layer && g.NavWindow)
7932  {
7933  // Move to parent menu if necessary
7934  ImGuiWindow* new_nav_window = g.NavWindow;
7935  while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0
7936  && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
7937  && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
7938  new_nav_window = new_nav_window->ParentWindow;
7939  if (new_nav_window != g.NavWindow)
7940  {
7941  ImGuiWindow* old_nav_window = g.NavWindow;
7942  FocusWindow(new_nav_window);
7943  new_nav_window->NavLastChildNavWindow = old_nav_window;
7944  }
7945  g.NavDisableHighlight = false;
7946  g.NavDisableMouseHover = true;
7948  }
7949 }
7950 
7951 // Window has already passed the IsWindowNavFocusable()
7953 {
7954  if (window->Flags & ImGuiWindowFlags_Popup)
7955  return "(Popup)";
7956  if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0)
7957  return "(Main menu bar)";
7958  return "(Untitled)";
7959 }
7960 
7961 // Overlay displayed when using CTRL+TAB. Called by EndFrame().
7963 {
7964  ImGuiContext& g = *GImGui;
7965  IM_ASSERT(g.NavWindowingTarget != NULL);
7966 
7968  return;
7969 
7970  if (g.NavWindowingList == NULL)
7971  g.NavWindowingList = FindWindowByName("###NavWindowingList");
7972  SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
7976  for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
7977  {
7978  ImGuiWindow* window = g.WindowsFocusOrder[n];
7979  if (!IsWindowNavFocusable(window))
7980  continue;
7981  const char* label = window->Name;
7982  if (label == FindRenderedTextEnd(label))
7983  label = GetFallbackWindowNameForWindowingList(window);
7984  Selectable(label, g.NavWindowingTarget == window);
7985  }
7986  End();
7987  PopStyleVar();
7988 }
7989 
7990 //-----------------------------------------------------------------------------
7991 // [SECTION] COLUMNS
7992 // In the current version, Columns are very weak. Needs to be replaced with a more full-featured system.
7993 //-----------------------------------------------------------------------------
7994 
7996 {
7997  ImGuiWindow* window = GetCurrentWindow();
7998  if (window->SkipItems || window->DC.ColumnsSet == NULL)
7999  return;
8000 
8001  ImGuiContext& g = *GImGui;
8002  PopItemWidth();
8003  PopClipRect();
8004 
8005  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8006  columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8007  if (++columns->Current < columns->Count)
8008  {
8009  // Columns 1+ cancel out IndentX
8010  window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x;
8011  window->DrawList->ChannelsSetCurrent(columns->Current);
8012  }
8013  else
8014  {
8015  window->DC.ColumnsOffset.x = 0.0f;
8016  window->DrawList->ChannelsSetCurrent(0);
8017  columns->Current = 0;
8018  columns->LineMinY = columns->LineMaxY;
8019  }
8020  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8021  window->DC.CursorPos.y = columns->LineMinY;
8022  window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
8023  window->DC.CurrentLineTextBaseOffset = 0.0f;
8024 
8026  PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup
8027 }
8028 
8030 {
8031  ImGuiWindow* window = GetCurrentWindowRead();
8032  return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0;
8033 }
8034 
8036 {
8037  ImGuiWindow* window = GetCurrentWindowRead();
8038  return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1;
8039 }
8040 
8041 static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm)
8042 {
8043  return offset_norm * (columns->MaxX - columns->MinX);
8044 }
8045 
8046 static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset)
8047 {
8048  return offset / (columns->MaxX - columns->MinX);
8049 }
8050 
8051 static inline float GetColumnsRectHalfWidth() { return 4.0f; }
8052 
8053 static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index)
8054 {
8055  // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
8056  // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
8057  ImGuiContext& g = *GImGui;
8058  ImGuiWindow* window = g.CurrentWindow;
8059  IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
8060  IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
8061 
8062  float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x;
8063  x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
8064  if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths))
8065  x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
8066 
8067  return x;
8068 }
8069 
8070 float ImGui::GetColumnOffset(int column_index)
8071 {
8072  ImGuiWindow* window = GetCurrentWindowRead();
8073  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8074  IM_ASSERT(columns != NULL);
8075 
8076  if (column_index < 0)
8077  column_index = columns->Current;
8078  IM_ASSERT(column_index < columns->Columns.Size);
8079 
8080  const float t = columns->Columns[column_index].OffsetNorm;
8081  const float x_offset = ImLerp(columns->MinX, columns->MaxX, t);
8082  return x_offset;
8083 }
8084 
8085 static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false)
8086 {
8087  if (column_index < 0)
8088  column_index = columns->Current;
8089 
8090  float offset_norm;
8091  if (before_resize)
8092  offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize;
8093  else
8094  offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm;
8095  return OffsetNormToPixels(columns, offset_norm);
8096 }
8097 
8098 float ImGui::GetColumnWidth(int column_index)
8099 {
8100  ImGuiWindow* window = GetCurrentWindowRead();
8101  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8102  IM_ASSERT(columns != NULL);
8103 
8104  if (column_index < 0)
8105  column_index = columns->Current;
8106  return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm);
8107 }
8108 
8109 void ImGui::SetColumnOffset(int column_index, float offset)
8110 {
8111  ImGuiContext& g = *GImGui;
8112  ImGuiWindow* window = g.CurrentWindow;
8113  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8114  IM_ASSERT(columns != NULL);
8115 
8116  if (column_index < 0)
8117  column_index = columns->Current;
8118  IM_ASSERT(column_index < columns->Columns.Size);
8119 
8120  const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1);
8121  const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
8122 
8123  if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
8124  offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
8125  columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX);
8126 
8127  if (preserve_width)
8128  SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
8129 }
8130 
8131 void ImGui::SetColumnWidth(int column_index, float width)
8132 {
8133  ImGuiWindow* window = GetCurrentWindowRead();
8134  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8135  IM_ASSERT(columns != NULL);
8136 
8137  if (column_index < 0)
8138  column_index = columns->Current;
8139  SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width);
8140 }
8141 
8142 void ImGui::PushColumnClipRect(int column_index)
8143 {
8144  ImGuiWindow* window = GetCurrentWindowRead();
8145  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8146  if (column_index < 0)
8147  column_index = columns->Current;
8148 
8149  PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false);
8150 }
8151 
8153 {
8154  for (int n = 0; n < window->ColumnsStorage.Size; n++)
8155  if (window->ColumnsStorage[n].ID == id)
8156  return &window->ColumnsStorage[n];
8157 
8159  ImGuiColumnsSet* columns = &window->ColumnsStorage.back();
8160  columns->ID = id;
8161  return columns;
8162 }
8163 
8164 void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags)
8165 {
8166  ImGuiContext& g = *GImGui;
8167  ImGuiWindow* window = GetCurrentWindow();
8168 
8169  IM_ASSERT(columns_count > 1);
8170  IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported
8171 
8172  // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.
8173  // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.
8174  PushID(0x11223347 + (str_id ? 0 : columns_count));
8175  ImGuiID id = window->GetID(str_id ? str_id : "columns");
8176  PopID();
8177 
8178  // Acquire storage for the columns set
8179  ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id);
8180  IM_ASSERT(columns->ID == id);
8181  columns->Current = 0;
8182  columns->Count = columns_count;
8183  columns->Flags = flags;
8184  window->DC.ColumnsSet = columns;
8185 
8186  // Set state for first column
8187  const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x);
8188  columns->MinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
8189  columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f);
8190  columns->StartPosY = window->DC.CursorPos.y;
8191  columns->StartMaxPosX = window->DC.CursorMaxPos.x;
8192  columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
8193  window->DC.ColumnsOffset.x = 0.0f;
8194  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8195 
8196  // Clear data if columns count changed
8197  if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
8198  columns->Columns.resize(0);
8199 
8200  // Initialize defaults
8201  columns->IsFirstFrame = (columns->Columns.Size == 0);
8202  if (columns->Columns.Size == 0)
8203  {
8204  columns->Columns.reserve(columns_count + 1);
8205  for (int n = 0; n < columns_count + 1; n++)
8206  {
8207  ImGuiColumnData column;
8208  column.OffsetNorm = n / (float)columns_count;
8209  columns->Columns.push_back(column);
8210  }
8211  }
8212 
8213  for (int n = 0; n < columns_count; n++)
8214  {
8215  // Compute clipping rectangle
8216  ImGuiColumnData* column = &columns->Columns[n];
8217  float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f);
8218  float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
8219  column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
8220  column->ClipRect.ClipWith(window->ClipRect);
8221  }
8222 
8223  window->DrawList->ChannelsSplit(columns->Count);
8225  PushItemWidth(GetColumnWidth() * 0.65f);
8226 }
8227 
8229 {
8230  ImGuiContext& g = *GImGui;
8231  ImGuiWindow* window = GetCurrentWindow();
8232  ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8233  IM_ASSERT(columns != NULL);
8234 
8235  PopItemWidth();
8236  PopClipRect();
8237  window->DrawList->ChannelsMerge();
8238 
8239  columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8240  window->DC.CursorPos.y = columns->LineMaxY;
8242  window->DC.CursorMaxPos.x = columns->StartMaxPosX; // Restore cursor max pos, as columns don't grow parent
8243 
8244  // Draw columns borders and handle resize
8245  bool is_being_resized = false;
8246  if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
8247  {
8248  const float y1 = columns->StartPosY;
8249  const float y2 = window->DC.CursorPos.y;
8250  int dragging_column = -1;
8251  for (int n = 1; n < columns->Count; n++)
8252  {
8253  float x = window->Pos.x + GetColumnOffset(n);
8254  const ImGuiID column_id = columns->ID + ImGuiID(n);
8255  const float column_hw = GetColumnsRectHalfWidth(); // Half-width for interaction
8256  const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2));
8257  KeepAliveID(column_id);
8258  if (IsClippedEx(column_rect, column_id, false))
8259  continue;
8260 
8261  bool hovered = false, held = false;
8262  if (!(columns->Flags & ImGuiColumnsFlags_NoResize))
8263  {
8264  ButtonBehavior(column_rect, column_id, &hovered, &held);
8265  if (hovered || held)
8267  if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize))
8268  dragging_column = n;
8269  }
8270 
8271  // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.)
8273  const float xi = (float)(int)x;
8274  window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col);
8275  }
8276 
8277  // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
8278  if (dragging_column != -1)
8279  {
8280  if (!columns->IsBeingResized)
8281  for (int n = 0; n < columns->Count + 1; n++)
8282  columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm;
8283  columns->IsBeingResized = is_being_resized = true;
8284  float x = GetDraggedColumnOffset(columns, dragging_column);
8285  SetColumnOffset(dragging_column, x);
8286  }
8287  }
8288  columns->IsBeingResized = is_being_resized;
8289 
8290  window->DC.ColumnsSet = NULL;
8291  window->DC.ColumnsOffset.x = 0.0f;
8292  window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8293 }
8294 
8295 // [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]
8296 void ImGui::Columns(int columns_count, const char* id, bool border)
8297 {
8298  ImGuiWindow* window = GetCurrentWindow();
8299  IM_ASSERT(columns_count >= 1);
8300 
8301  ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
8302  //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
8303  if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags)
8304  return;
8305 
8306  if (window->DC.ColumnsSet != NULL)
8307  EndColumns();
8308 
8309  if (columns_count != 1)
8310  BeginColumns(id, columns_count, flags);
8311 }
8312 
8313 //-----------------------------------------------------------------------------
8314 // [SECTION] DRAG AND DROP
8315 //-----------------------------------------------------------------------------
8316 
8318 {
8319  ImGuiContext& g = *GImGui;
8320  g.DragDropActive = false;
8321  g.DragDropPayload.Clear();
8324  g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
8325  g.DragDropAcceptFrameCount = -1;
8326 
8328  memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
8329 }
8330 
8331 // Call when current ID is active.
8332 // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
8334 {
8335  ImGuiContext& g = *GImGui;
8336  ImGuiWindow* window = g.CurrentWindow;
8337 
8338  bool source_drag_active = false;
8339  ImGuiID source_id = 0;
8340  ImGuiID source_parent_id = 0;
8341  int mouse_button = 0;
8342  if (!(flags & ImGuiDragDropFlags_SourceExtern))
8343  {
8344  source_id = window->DC.LastItemId;
8345  if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
8346  return false;
8347  if (g.IO.MouseDown[mouse_button] == false)
8348  return false;
8349 
8350  if (source_id == 0)
8351  {
8352  // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
8353  // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
8354  if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
8355  {
8356  IM_ASSERT(0);
8357  return false;
8358  }
8359 
8360  // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
8361  // We build a throwaway ID based on current ID stack + relative AABB of items in window.
8362  // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
8363  // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
8364  bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0;
8365  if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
8366  return false;
8367  source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
8368  if (is_hovered)
8369  SetHoveredID(source_id);
8370  if (is_hovered && g.IO.MouseClicked[mouse_button])
8371  {
8372  SetActiveID(source_id, window);
8373  FocusWindow(window);
8374  }
8375  if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
8376  g.ActiveIdAllowOverlap = is_hovered;
8377  }
8378  else
8379  {
8380  g.ActiveIdAllowOverlap = false;
8381  }
8382  if (g.ActiveId != source_id)
8383  return false;
8384  source_parent_id = window->IDStack.back();
8385  source_drag_active = IsMouseDragging(mouse_button);
8386  }
8387  else
8388  {
8389  window = NULL;
8390  source_id = ImHash("#SourceExtern", 0);
8391  source_drag_active = true;
8392  }
8393 
8394  if (source_drag_active)
8395  {
8396  if (!g.DragDropActive)
8397  {
8398  IM_ASSERT(source_id != 0);
8399  ClearDragDrop();
8400  ImGuiPayload& payload = g.DragDropPayload;
8401  payload.SourceId = source_id;
8402  payload.SourceParentId = source_parent_id;
8403  g.DragDropActive = true;
8404  g.DragDropSourceFlags = flags;
8405  g.DragDropMouseButton = mouse_button;
8406  }
8409 
8411  {
8412  // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
8413  // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
8414  BeginTooltip();
8416  {
8417  ImGuiWindow* tooltip_window = g.CurrentWindow;
8418  tooltip_window->SkipItems = true;
8419  tooltip_window->HiddenFramesRegular = 1;
8420  }
8421  }
8422 
8423  if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
8425 
8426  return true;
8427  }
8428  return false;
8429 }
8430 
8432 {
8433  ImGuiContext& g = *GImGui;
8435  IM_ASSERT(g.DragDropWithinSourceOrTarget && "Not after a BeginDragDropSource()?");
8436 
8438  EndTooltip();
8439 
8440  // Discard the drag if have not called SetDragDropPayload()
8441  if (g.DragDropPayload.DataFrameCount == -1)
8442  ClearDragDrop();
8443  g.DragDropWithinSourceOrTarget = false;
8444 }
8445 
8446 // Use 'cond' to choose to submit payload on drag start or every frame
8447 bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
8448 {
8449  ImGuiContext& g = *GImGui;
8450  ImGuiPayload& payload = g.DragDropPayload;
8451  if (cond == 0)
8452  cond = ImGuiCond_Always;
8453 
8454  IM_ASSERT(type != NULL);
8455  IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
8456  IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
8457  IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
8458  IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
8459 
8460  if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
8461  {
8462  // Copy payload
8463  ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
8465  if (data_size > sizeof(g.DragDropPayloadBufLocal))
8466  {
8467  // Store in heap
8468  g.DragDropPayloadBufHeap.resize((int)data_size);
8469  payload.Data = g.DragDropPayloadBufHeap.Data;
8470  memcpy(payload.Data, data, data_size);
8471  }
8472  else if (data_size > 0)
8473  {
8474  // Store locally
8475  memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
8476  payload.Data = g.DragDropPayloadBufLocal;
8477  memcpy(payload.Data, data, data_size);
8478  }
8479  else
8480  {
8481  payload.Data = NULL;
8482  }
8483  payload.DataSize = (int)data_size;
8484  }
8485  payload.DataFrameCount = g.FrameCount;
8486 
8488 }
8489 
8491 {
8492  ImGuiContext& g = *GImGui;
8493  if (!g.DragDropActive)
8494  return false;
8495 
8496  ImGuiWindow* window = g.CurrentWindow;
8497  if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8498  return false;
8499  IM_ASSERT(id != 0);
8500  if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
8501  return false;
8502  if (window->SkipItems)
8503  return false;
8504 
8506  g.DragDropTargetRect = bb;
8507  g.DragDropTargetId = id;
8509  return true;
8510 }
8511 
8512 // We don't use BeginDragDropTargetCustom() and duplicate its code because:
8513 // 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them.
8514 // 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can.
8515 // Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case)
8517 {
8518  ImGuiContext& g = *GImGui;
8519  if (!g.DragDropActive)
8520  return false;
8521 
8522  ImGuiWindow* window = g.CurrentWindow;
8524  return false;
8525  if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8526  return false;
8527 
8528  const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
8529  ImGuiID id = window->DC.LastItemId;
8530  if (id == 0)
8531  id = window->GetIDFromRectangle(display_rect);
8532  if (g.DragDropPayload.SourceId == id)
8533  return false;
8534 
8536  g.DragDropTargetRect = display_rect;
8537  g.DragDropTargetId = id;
8539  return true;
8540 }
8541 
8543 {
8544  ImGuiContext& g = *GImGui;
8545  return g.DragDropActive && g.DragDropAcceptIdPrev != 0;
8546 }
8547 
8549 {
8550  ImGuiContext& g = *GImGui;
8551  ImGuiWindow* window = g.CurrentWindow;
8552  ImGuiPayload& payload = g.DragDropPayload;
8553  IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
8554  IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ?
8555  if (type != NULL && !payload.IsDataType(type))
8556  return NULL;
8557 
8558  // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints.
8559  // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function!
8560  const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId);
8561  ImRect r = g.DragDropTargetRect;
8562  float r_surface = r.GetWidth() * r.GetHeight();
8563  if (r_surface < g.DragDropAcceptIdCurrRectSurface)
8564  {
8565  g.DragDropAcceptFlags = flags;
8567  g.DragDropAcceptIdCurrRectSurface = r_surface;
8568  }
8569 
8570  // Render default drop visuals
8571  payload.Preview = was_accepted_previously;
8572  flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
8573  if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
8574  {
8575  // FIXME-DRAG: Settle on a proper default visuals for drop target.
8576  r.Expand(3.5f);
8577  bool push_clip_rect = !window->ClipRect.Contains(r);
8578  if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1));
8579  window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
8580  if (push_clip_rect) window->DrawList->PopClipRect();
8581  }
8582 
8584  payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
8585  if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
8586  return NULL;
8587 
8588  return &payload;
8589 }
8590 
8592 {
8593  ImGuiContext& g = *GImGui;
8594  return g.DragDropActive ? &g.DragDropPayload : NULL;
8595 }
8596 
8597 // We don't really use/need this now, but added it for the sake of consistency and because we might need it later.
8599 {
8600  ImGuiContext& g = *GImGui;
8603  g.DragDropWithinSourceOrTarget = false;
8604 }
8605 
8606 //-----------------------------------------------------------------------------
8607 // [SECTION] DOCKING
8608 //-----------------------------------------------------------------------------
8609 
8610 // (this section is filled in the 'docking' branch)
8611 
8612 //-----------------------------------------------------------------------------
8613 // [SECTION] LOGGING/CAPTURING
8614 //-----------------------------------------------------------------------------
8615 
8616 // Pass text data straight to log (without being displayed)
8617 void ImGui::LogText(const char* fmt, ...)
8618 {
8619  ImGuiContext& g = *GImGui;
8620  if (!g.LogEnabled)
8621  return;
8622 
8623  va_list args;
8624  va_start(args, fmt);
8625  if (g.LogFile)
8626  vfprintf(g.LogFile, fmt, args);
8627  else
8628  g.LogClipboard.appendfv(fmt, args);
8629  va_end(args);
8630 }
8631 
8632 // Internal version that takes a position to decide on newline placement and pad items according to their depth.
8633 // We split text into individual lines to add current tree level padding
8634 void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
8635 {
8636  ImGuiContext& g = *GImGui;
8637  ImGuiWindow* window = g.CurrentWindow;
8638 
8639  if (!text_end)
8640  text_end = FindRenderedTextEnd(text, text_end);
8641 
8642  const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1);
8643  if (ref_pos)
8644  window->DC.LogLinePosY = ref_pos->y;
8645 
8646  const char* text_remaining = text;
8647  if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
8648  g.LogStartDepth = window->DC.TreeDepth;
8649  const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
8650  for (;;)
8651  {
8652  // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
8653  const char* line_start = text_remaining;
8654  const char* line_end = ImStreolRange(line_start, text_end);
8655  const bool is_first_line = (line_start == text);
8656  const bool is_last_line = (line_end == text_end);
8657  if (!is_last_line || (line_start != line_end))
8658  {
8659  const int char_count = (int)(line_end - line_start);
8660  if (log_new_line || !is_first_line)
8661  LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start);
8662  else
8663  LogText(" %.*s", char_count, line_start);
8664  }
8665 
8666  if (is_last_line)
8667  break;
8668  text_remaining = line_end + 1;
8669  }
8670 }
8671 
8672 // Start logging ImGui output to TTY
8673 void ImGui::LogToTTY(int max_depth)
8674 {
8675  ImGuiContext& g = *GImGui;
8676  if (g.LogEnabled)
8677  return;
8678  ImGuiWindow* window = g.CurrentWindow;
8679 
8680  IM_ASSERT(g.LogFile == NULL);
8681  g.LogFile = stdout;
8682  g.LogEnabled = true;
8683  g.LogStartDepth = window->DC.TreeDepth;
8684  if (max_depth >= 0)
8685  g.LogAutoExpandMaxDepth = max_depth;
8686 }
8687 
8688 // Start logging ImGui output to given file
8689 void ImGui::LogToFile(int max_depth, const char* filename)
8690 {
8691  ImGuiContext& g = *GImGui;
8692  if (g.LogEnabled)
8693  return;
8694  ImGuiWindow* window = g.CurrentWindow;
8695 
8696  if (!filename)
8697  {
8698  filename = g.IO.LogFilename;
8699  if (!filename)
8700  return;
8701  }
8702 
8703  IM_ASSERT(g.LogFile == NULL);
8704  g.LogFile = ImFileOpen(filename, "ab");
8705  if (!g.LogFile)
8706  {
8707  IM_ASSERT(g.LogFile != NULL); // Consider this an error
8708  return;
8709  }
8710  g.LogEnabled = true;
8711  g.LogStartDepth = window->DC.TreeDepth;
8712  if (max_depth >= 0)
8713  g.LogAutoExpandMaxDepth = max_depth;
8714 }
8715 
8716 // Start logging ImGui output to clipboard
8717 void ImGui::LogToClipboard(int max_depth)
8718 {
8719  ImGuiContext& g = *GImGui;
8720  if (g.LogEnabled)
8721  return;
8722  ImGuiWindow* window = g.CurrentWindow;
8723 
8724  IM_ASSERT(g.LogFile == NULL);
8725  g.LogFile = NULL;
8726  g.LogEnabled = true;
8727  g.LogStartDepth = window->DC.TreeDepth;
8728  if (max_depth >= 0)
8729  g.LogAutoExpandMaxDepth = max_depth;
8730 }
8731 
8733 {
8734  ImGuiContext& g = *GImGui;
8735  if (!g.LogEnabled)
8736  return;
8737 
8739  if (g.LogFile != NULL)
8740  {
8741  if (g.LogFile == stdout)
8742  fflush(g.LogFile);
8743  else
8744  fclose(g.LogFile);
8745  g.LogFile = NULL;
8746  }
8747  if (g.LogClipboard.size() > 1)
8748  {
8750  g.LogClipboard.clear();
8751  }
8752  g.LogEnabled = false;
8753 }
8754 
8755 // Helper to display logging buttons
8757 {
8758  ImGuiContext& g = *GImGui;
8759 
8760  PushID("LogButtons");
8761  const bool log_to_tty = Button("Log To TTY"); SameLine();
8762  const bool log_to_file = Button("Log To File"); SameLine();
8763  const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
8764  PushItemWidth(80.0f);
8765  PushAllowKeyboardFocus(false);
8766  SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL);
8768  PopItemWidth();
8769  PopID();
8770 
8771  // Start logging at the end of the function so that the buttons don't appear in the log
8772  if (log_to_tty)
8774  if (log_to_file)
8776  if (log_to_clipboard)
8778 }
8779 
8780 //-----------------------------------------------------------------------------
8781 // [SECTION] SETTINGS
8782 //-----------------------------------------------------------------------------
8783 
8785 {
8786  ImGuiContext& g = *GImGui;
8787  if (g.SettingsDirtyTimer <= 0.0f)
8789 }
8790 
8792 {
8793  ImGuiContext& g = *GImGui;
8794  if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
8795  if (g.SettingsDirtyTimer <= 0.0f)
8797 }
8798 
8800 {
8801  ImGuiContext& g = *GImGui;
8803  ImGuiWindowSettings* settings = &g.SettingsWindows.back();
8804  settings->Name = ImStrdup(name);
8805  settings->ID = ImHash(name, 0);
8806  return settings;
8807 }
8808 
8810 {
8811  ImGuiContext& g = *GImGui;
8812  for (int i = 0; i != g.SettingsWindows.Size; i++)
8813  if (g.SettingsWindows[i].ID == id)
8814  return &g.SettingsWindows[i];
8815  return NULL;
8816 }
8817 
8818 void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
8819 {
8820  size_t file_data_size = 0;
8821  char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size);
8822  if (!file_data)
8823  return;
8824  LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
8825  ImGui::MemFree(file_data);
8826 }
8827 
8829 {
8830  ImGuiContext& g = *GImGui;
8831  const ImGuiID type_hash = ImHash(type_name, 0, 0);
8832  for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
8833  if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
8834  return &g.SettingsHandlers[handler_n];
8835  return NULL;
8836 }
8837 
8838 // Zero-tolerance, no error reporting, cheap .ini parsing
8839 void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
8840 {
8841  ImGuiContext& g = *GImGui;
8843  IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0);
8844 
8845  // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
8846  // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
8847  if (ini_size == 0)
8848  ini_size = strlen(ini_data);
8849  char* buf = (char*)ImGui::MemAlloc(ini_size + 1);
8850  char* buf_end = buf + ini_size;
8851  memcpy(buf, ini_data, ini_size);
8852  buf[ini_size] = 0;
8853 
8854  void* entry_data = NULL;
8855  ImGuiSettingsHandler* entry_handler = NULL;
8856 
8857  char* line_end = NULL;
8858  for (char* line = buf; line < buf_end; line = line_end + 1)
8859  {
8860  // Skip new lines markers, then find end of the line
8861  while (*line == '\n' || *line == '\r')
8862  line++;
8863  line_end = line;
8864  while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
8865  line_end++;
8866  line_end[0] = 0;
8867  if (line[0] == ';')
8868  continue;
8869  if (line[0] == '[' && line_end > line && line_end[-1] == ']')
8870  {
8871  // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
8872  line_end[-1] = 0;
8873  const char* name_end = line_end - 1;
8874  const char* type_start = line + 1;
8875  char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']');
8876  const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
8877  if (!type_end || !name_start)
8878  {
8879  name_start = type_start; // Import legacy entries that have no type
8880  type_start = "Window";
8881  }
8882  else
8883  {
8884  *type_end = 0; // Overwrite first ']'
8885  name_start++; // Skip second '['
8886  }
8887  entry_handler = FindSettingsHandler(type_start);
8888  entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL;
8889  }
8890  else if (entry_handler != NULL && entry_data != NULL)
8891  {
8892  // Let type handler parse the line
8893  entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
8894  }
8895  }
8896  ImGui::MemFree(buf);
8897  g.SettingsLoaded = true;
8898 }
8899 
8900 void ImGui::SaveIniSettingsToDisk(const char* ini_filename)
8901 {
8902  ImGuiContext& g = *GImGui;
8903  g.SettingsDirtyTimer = 0.0f;
8904  if (!ini_filename)
8905  return;
8906 
8907  size_t ini_data_size = 0;
8908  const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
8909  FILE* f = ImFileOpen(ini_filename, "wt");
8910  if (!f)
8911  return;
8912  fwrite(ini_data, sizeof(char), ini_data_size, f);
8913  fclose(f);
8914 }
8915 
8916 // Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
8917 const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
8918 {
8919  ImGuiContext& g = *GImGui;
8920  g.SettingsDirtyTimer = 0.0f;
8921  g.SettingsIniData.Buf.resize(0);
8923  for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
8924  {
8925  ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n];
8926  handler->WriteAllFn(&g, handler, &g.SettingsIniData);
8927  }
8928  if (out_size)
8929  *out_size = (size_t)g.SettingsIniData.size();
8930  return g.SettingsIniData.c_str();
8931 }
8932 
8934 {
8936  if (!settings)
8937  settings = ImGui::CreateNewWindowSettings(name);
8938  return (void*)settings;
8939 }
8940 
8941 static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
8942 {
8943  ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
8944  float x, y;
8945  int i;
8946  if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y);
8947  else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize);
8948  else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0);
8949 }
8950 
8952 {
8953  // Gather data from windows that were active during this session
8954  // (if a window wasn't opened in this session we preserve its settings)
8955  ImGuiContext& g = *imgui_ctx;
8956  for (int i = 0; i != g.Windows.Size; i++)
8957  {
8958  ImGuiWindow* window = g.Windows[i];
8960  continue;
8961 
8962  ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID);
8963  if (!settings)
8964  {
8965  settings = ImGui::CreateNewWindowSettings(window->Name);
8966  window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
8967  }
8968  IM_ASSERT(settings->ID == window->ID);
8969  settings->Pos = window->Pos;
8970  settings->Size = window->SizeFull;
8971  settings->Collapsed = window->Collapsed;
8972  }
8973 
8974  // Write to text buffer
8975  buf->reserve(buf->size() + g.SettingsWindows.Size * 96); // ballpark reserve
8976  for (int i = 0; i != g.SettingsWindows.Size; i++)
8977  {
8978  const ImGuiWindowSettings* settings = &g.SettingsWindows[i];
8979  if (settings->Pos.x == FLT_MAX)
8980  continue;
8981  const char* name = settings->Name;
8982  if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
8983  name = p;
8984  buf->appendf("[%s][%s]\n", handler->TypeName, name);
8985  buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
8986  buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
8987  buf->appendf("Collapsed=%d\n", settings->Collapsed);
8988  buf->appendf("\n");
8989  }
8990 }
8991 
8992 //-----------------------------------------------------------------------------
8993 // [SECTION] PLATFORM DEPENDENT HELPERS
8994 //-----------------------------------------------------------------------------
8995 
8996 #if defined(_WIN32) && !defined(_WINDOWS_) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS))
8997 #ifndef WIN32_LEAN_AND_MEAN
8998 #define WIN32_LEAN_AND_MEAN
8999 #endif
9000 #ifndef __MINGW32__
9001 #include <Windows.h>
9002 #else
9003 #include <windows.h>
9004 #endif
9005 #endif
9006 
9007 // Win32 API clipboard implementation
9008 #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
9009 
9010 #ifdef _MSC_VER
9011 #pragma comment(lib, "user32")
9012 #endif
9013 
9014 static const char* GetClipboardTextFn_DefaultImpl(void*)
9015 {
9016  static ImVector<char> buf_local;
9017  buf_local.clear();
9018  if (!::OpenClipboard(NULL))
9019  return NULL;
9020  HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
9021  if (wbuf_handle == NULL)
9022  {
9023  ::CloseClipboard();
9024  return NULL;
9025  }
9026  if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle))
9027  {
9028  int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
9029  buf_local.resize(buf_len);
9030  ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);
9031  }
9032  ::GlobalUnlock(wbuf_handle);
9033  ::CloseClipboard();
9034  return buf_local.Data;
9035 }
9036 
9037 static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
9038 {
9039  if (!::OpenClipboard(NULL))
9040  return;
9041  const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
9042  HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
9043  if (wbuf_handle == NULL)
9044  {
9045  ::CloseClipboard();
9046  return;
9047  }
9048  ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle);
9049  ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
9050  ::GlobalUnlock(wbuf_handle);
9051  ::EmptyClipboard();
9052  if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
9053  ::GlobalFree(wbuf_handle);
9054  ::CloseClipboard();
9055 }
9056 
9057 #else
9058 
9059 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
9060 static const char* GetClipboardTextFn_DefaultImpl(void*)
9061 {
9062  ImGuiContext& g = *GImGui;
9063  return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin();
9064 }
9065 
9066 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
9067 static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
9068 {
9069  ImGuiContext& g = *GImGui;
9070  g.PrivateClipboard.clear();
9071  const char* text_end = text + strlen(text);
9072  g.PrivateClipboard.resize((int)(text_end - text) + 1);
9073  memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text));
9074  g.PrivateClipboard[(int)(text_end - text)] = 0;
9075 }
9076 
9077 #endif
9078 
9079 // Win32 API IME support (for Asian languages, etc.)
9080 #if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
9081 
9082 #include <imm.h>
9083 #ifdef _MSC_VER
9084 #pragma comment(lib, "imm32")
9085 #endif
9086 
9087 static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
9088 {
9089  // Notify OS Input Method Editor of text input position
9090  if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)
9091  if (HIMC himc = ::ImmGetContext(hwnd))
9092  {
9093  COMPOSITIONFORM cf;
9094  cf.ptCurrentPos.x = x;
9095  cf.ptCurrentPos.y = y;
9096  cf.dwStyle = CFS_FORCE_POSITION;
9097  ::ImmSetCompositionWindow(himc, &cf);
9098  ::ImmReleaseContext(hwnd, himc);
9099  }
9100 }
9101 
9102 #else
9103 
9104 static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
9105 
9106 #endif
9107 
9108 //-----------------------------------------------------------------------------
9109 // [SECTION] METRICS/DEBUG WINDOW
9110 //-----------------------------------------------------------------------------
9111 
9112 void ImGui::ShowMetricsWindow(bool* p_open)
9113 {
9114  if (!ImGui::Begin("ImGui Metrics", p_open))
9115  {
9116  ImGui::End();
9117  return;
9118  }
9119 
9120  static bool show_draw_cmd_clip_rects = true;
9121  static bool show_window_begin_order = false;
9122  ImGuiIO& io = ImGui::GetIO();
9123  ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
9124  ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
9125  ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
9126  ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
9127  ImGui::Text("%d allocations", io.MetricsActiveAllocations);
9128  ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_draw_cmd_clip_rects);
9129  ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order);
9130  ImGui::Separator();
9131 
9132  struct Funcs
9133  {
9134  static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label)
9135  {
9136  bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);
9137  if (draw_list == ImGui::GetWindowDrawList())
9138  {
9139  ImGui::SameLine();
9140  ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
9141  if (node_open) ImGui::TreePop();
9142  return;
9143  }
9144 
9145  ImDrawList* overlay_draw_list = GetOverlayDrawList(window); // Render additional visuals into the top-most draw list
9146  if (window && IsItemHovered())
9147  overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
9148  if (!node_open)
9149  return;
9150 
9151  int elem_offset = 0;
9152  for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)
9153  {
9154  if (pcmd->UserCallback == NULL && pcmd->ElemCount == 0)
9155  continue;
9156  if (pcmd->UserCallback)
9157  {
9158  ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
9159  continue;
9160  }
9161  ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
9162  bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
9163  if (show_draw_cmd_clip_rects && ImGui::IsItemHovered())
9164  {
9165  ImRect clip_rect = pcmd->ClipRect;
9166  ImRect vtxs_rect;
9167  for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)
9168  vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos);
9169  clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255));
9170  vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255));
9171  }
9172  if (!pcmd_node_open)
9173  continue;
9174 
9175  // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
9176  ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
9177  while (clipper.Step())
9178  for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
9179  {
9180  char buf[300];
9181  char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
9182  ImVec2 triangles_pos[3];
9183  for (int n = 0; n < 3; n++, vtx_i++)
9184  {
9185  ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i];
9186  triangles_pos[n] = v.pos;
9187  buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
9188  }
9189  ImGui::Selectable(buf, false);
9190  if (ImGui::IsItemHovered())
9191  {
9192  ImDrawListFlags backup_flags = overlay_draw_list->Flags;
9193  overlay_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles.
9194  overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f);
9195  overlay_draw_list->Flags = backup_flags;
9196  }
9197  }
9198  ImGui::TreePop();
9199  }
9200  ImGui::TreePop();
9201  }
9202 
9203  static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* label)
9204  {
9205  if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size))
9206  return;
9207  for (int i = 0; i < windows.Size; i++)
9208  Funcs::NodeWindow(windows[i], "Window");
9209  ImGui::TreePop();
9210  }
9211 
9212  static void NodeWindow(ImGuiWindow* window, const char* label)
9213  {
9214  if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
9215  return;
9216  ImGuiWindowFlags flags = window->Flags;
9217  NodeDrawList(window, window->DrawList, "DrawList");
9218  ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y);
9219  ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
9220  (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "",
9221  (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "",
9222  (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : "");
9223  ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window));
9224  ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
9225  ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems);
9226  ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
9227  ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
9228  if (!window->NavRectRel[0].IsInverted())
9229  ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y);
9230  else
9231  ImGui::BulletText("NavRectRel[0]: <None>");
9232  if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
9233  if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow");
9234  if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
9235  if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
9236  {
9237  for (int n = 0; n < window->ColumnsStorage.Size; n++)
9238  {
9239  const ImGuiColumnsSet* columns = &window->ColumnsStorage[n];
9240  if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
9241  {
9242  ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX);
9243  for (int column_n = 0; column_n < columns->Columns.Size; column_n++)
9244  ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm));
9245  ImGui::TreePop();
9246  }
9247  }
9248  ImGui::TreePop();
9249  }
9250  ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
9251  ImGui::TreePop();
9252  }
9253 
9254  static void NodeTabBar(ImGuiTabBar* tab_bar)
9255  {
9256  // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernable strings.
9257  char buf[256];
9258  char* p = buf;
9259  const char* buf_end = buf + IM_ARRAYSIZE(buf);
9260  p += ImFormatString(p, buf_end - p, "TabBar (%d tabs)%s",
9261  tab_bar->Tabs.Size, (tab_bar->PrevFrameVisible < ImGui::GetFrameCount() - 2) ? " *Inactive*" : "");
9262  if (ImGui::TreeNode(tab_bar, "%s", buf))
9263  {
9264  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
9265  {
9266  const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
9267  ImGui::PushID(tab);
9268  if (ImGui::SmallButton("<")) { TabBarQueueChangeTabOrder(tab_bar, tab, -1); } ImGui::SameLine(0, 2);
9269  if (ImGui::SmallButton(">")) { TabBarQueueChangeTabOrder(tab_bar, tab, +1); } ImGui::SameLine();
9270  ImGui::Text("%02d%c Tab 0x%08X", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID);
9271  ImGui::PopID();
9272  }
9273  ImGui::TreePop();
9274  }
9275  }
9276  };
9277 
9278  // Access private state, we are going to display the draw lists from last frame
9279  ImGuiContext& g = *GImGui;
9280  Funcs::NodeWindows(g.Windows, "Windows");
9281  if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size))
9282  {
9283  for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++)
9284  Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList");
9285  ImGui::TreePop();
9286  }
9287  if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
9288  {
9289  for (int i = 0; i < g.OpenPopupStack.Size; i++)
9290  {
9291  ImGuiWindow* window = g.OpenPopupStack[i].Window;
9292  ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
9293  }
9294  ImGui::TreePop();
9295  }
9296  if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size))
9297  {
9298  for (int n = 0; n < g.TabBars.Data.Size; n++)
9299  Funcs::NodeTabBar(g.TabBars.GetByIndex(n));
9300  ImGui::TreePop();
9301  }
9302  if (ImGui::TreeNode("Internal state"))
9303  {
9304  const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
9305  ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
9306  ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
9307  ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
9308  ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
9309  ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
9310  ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
9311  ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
9312  ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
9313  ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
9314  ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
9315  ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
9316  ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
9317  ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
9318  ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
9319  ImGui::TreePop();
9320  }
9321 
9322 
9323  if (g.IO.KeyCtrl && show_window_begin_order)
9324  {
9325  for (int n = 0; n < g.Windows.Size; n++)
9326  {
9327  ImGuiWindow* window = g.Windows[n];
9328  if ((window->Flags & ImGuiWindowFlags_ChildWindow) || !window->WasActive)
9329  continue;
9330  char buf[32];
9331  ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
9332  float font_size = ImGui::GetFontSize() * 2;
9333  ImDrawList* overlay_draw_list = GetOverlayDrawList(window);
9334  overlay_draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
9335  overlay_draw_list->AddText(NULL, font_size, window->Pos, IM_COL32(255, 255, 255, 255), buf);
9336  }
9337  }
9338  ImGui::End();
9339 }
9340 
9341 //-----------------------------------------------------------------------------
9342 
9343 // Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed.
9344 // Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github.
9345 #ifdef IMGUI_INCLUDE_IMGUI_USER_INL
9346 #include "imgui_user.inl"
9347 #endif
9348 
9349 //-----------------------------------------------------------------------------
float NavInputs[ImGuiNavInput_COUNT]
Definition: imgui.h:1350
static void SettingsHandlerWindow_ReadLine(ImGuiContext *, ImGuiSettingsHandler *, void *entry, const char *line)
Definition: imgui.cpp:8941
~ImGuiWindow()
Definition: imgui.cpp:2496
IMGUI_API bool BeginPopupContextItem(const char *str_id=NULL, int mouse_button=1)
Definition: imgui.cpp:6832
d
ImGuiWindowTempData DC
#define IMGUI_DEBUG_NAV_SCORING
Definition: imgui.cpp:939
ImGuiDir NavMoveDirLast
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val)
Definition: imgui.cpp:5697
static void UpdateManualResize(ImGuiWindow *window, const ImVec2 &size_auto_fit, int *border_held, int resize_grip_count, ImU32 resize_grip_col[4])
Definition: imgui.cpp:4608
int ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
Definition: imgui.cpp:1387
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiCond cond=0)
Definition: imgui.cpp:6054
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow *window, ImGuiNavMoveFlags move_flags)
Definition: imgui.cpp:7235
ImRect MenuBarRect() const
bool WantSaveIniSettings
Definition: imgui.h:1365
ImVec2 BackupCursorPos
bool NavVisible
Definition: imgui.h:1367
#define NAV_MAP_KEY(_KEY, _NAV_INPUT)
const char *(* GetClipboardTextFn)(void *user_data)
Definition: imgui.h:1319
int FocusIdxTabRequestNext
float Framerate
Definition: imgui.h:1368
IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0)
Definition: imgui.cpp:5812
#define IMGUI_CDECL
IMGUI_API float GetCursorPosX()
Definition: imgui.cpp:6200
IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value=true)
Definition: imgui.cpp:4125
void PathStroke(ImU32 col, bool closed, float thickness=1.0f)
Definition: imgui.h:1844
void(* WriteAllFn)(ImGuiContext *ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *out_buf)
IMGUI_API float * GetFloatRef(ImGuiID key, float default_val=0.0f)
Definition: imgui.cpp:1904
ImGuiWindow * RootWindowForTitleBarHighlight
IMGUI_API ImVec2 GetCursorStartPos()
Definition: imgui.cpp:6233
IMGUI_API void ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
Definition: imgui.cpp:6712
unsigned int ImU32
Definition: imgui.h:150
ImVec2 DisplaySize
Definition: imgui.h:1887
IMGUI_API void SetTooltip(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:6576
IMGUI_API void RenderText(ImVec2 pos, const char *text, const char *text_end=NULL, bool hide_text_after_hash=true)
Definition: imgui.cpp:2224
IMGUI_API bool IsMouseReleased(int button)
Definition: imgui.cpp:4044
ImRect NavInitResultRectRel
bool MouseDrawCursor
Definition: imgui.h:1299
float WindowBorderSize
IMGUI_API void LoadIniSettingsFromMemory(const char *ini_data, size_t ini_size=0)
Definition: imgui.cpp:8839
ImDrawList ** CmdLists
Definition: imgui.h:1882
IMGUI_API bool DebugCheckVersionAndDataLayout(const char *version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert)
Definition: imgui.cpp:2937
static void FreeWrapper(void *ptr, void *user_data)
Definition: imgui.cpp:1050
void * GetVarPtr(ImGuiStyle *style) const
Definition: imgui.cpp:5661
IMGUI_API void UpdateMouseMovingWindowNewFrame()
Definition: imgui.cpp:3036
IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond=0)
Definition: imgui.cpp:6004
IMGUI_API ImVec2 GetCursorPos()
Definition: imgui.cpp:6194
static void AddWindowToSortBuffer(ImVector< ImGuiWindow *> *out_sorted_windows, ImGuiWindow *window)
Definition: imgui.cpp:3568
bool ConfigWindowsResizeFromEdges
Definition: imgui.h:1302
int ActiveIdAllowNavDirFlags
ImGuiCond SetWindowPosAllowFlags
ImDrawIdx * _IdxWritePtr
Definition: imgui.h:1800
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow *window)
Definition: imgui.cpp:5414
ImGuiNavMoveResult NavMoveResultLocalVisibleSet
ImVector< T > Data
int DragDropSourceFrameCount
bool ActiveIdIsJustActivated
const char * LogFilename
Definition: imgui.h:1281
IMGUI_API float GetFontSize()
Definition: imgui.cpp:6174
static void(* GImAllocatorFreeFunc)(void *ptr, void *user_data)
Definition: imgui.cpp:1057
static ImGuiColumnsSet * FindOrAddColumnsSet(ImGuiWindow *window, ImGuiID id)
Definition: imgui.cpp:8152
bool WantSetMousePos
Definition: imgui.h:1364
IMGUI_API void RenderMouseCursor(ImDrawList *draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor=ImGuiMouseCursor_Arrow)
int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1532
IMGUI_API void MarkIniSettingsDirty()
Definition: imgui.cpp:8784
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz)
Definition: imgui.cpp:2379
IMGUI_API void SetVoidPtr(ImGuiID key, void *val)
Definition: imgui.cpp:1948
static void FindHoveredWindow()
Definition: imgui.cpp:3898
char * ImStrdupcpy(char *dst, size_t *p_dst_size, const char *src)
Definition: imgui.cpp:1292
ImGuiWindow * ParentWindow
IMGUI_API void PushColumnClipRect(int column_index=-1)
Definition: imgui.cpp:8142
static float NavUpdatePageUpPageDown(int allowed_dir_flags)
Definition: imgui.cpp:7738
static void NavRestoreLayer(ImGuiNavLayer layer)
Definition: imgui.cpp:7285
IMGUI_API void PopTextureID()
Definition: imgui_draw.cpp:513
ImVec2 ActiveIdClickOffset
ROSCPP_DECL void start()
ImVec2 MousePos
Definition: imgui.h:1341
IMGUI_API void AddInputCharacter(ImWchar c)
Definition: imgui.cpp:1191
IMGUI_API void SetColumnWidth(int column_index, float width)
Definition: imgui.cpp:8131
ImGuiID ActiveIdIsAlive
float GetWidth() const
static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
Definition: imgui.cpp:2125
ImDrawData DrawData
float MouseCursorScale
Definition: imgui.h:1253
IMGUI_API ImGuiStorage * GetStateStorage()
Definition: imgui.cpp:6341
IMGUI_API void PopClipRect()
Definition: imgui_draw.cpp:500
double MouseClickedTime[5]
Definition: imgui.h:1382
void(* SetClipboardTextFn)(void *user_data, const char *text)
Definition: imgui.h:1320
void reserve(int capacity)
Definition: imgui.h:1583
void Clear()
Definition: imgui.h:1612
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow *ref_window)
Definition: imgui.cpp:6675
IMGUI_API const char * FindRenderedTextEnd(const char *text, const char *text_end=NULL)
Definition: imgui.cpp:2211
int WantCaptureMouseNextFrame
float GetHeight() const
IMGUI_API ImGuiWindowSettings * FindWindowSettings(ImGuiID id)
Definition: imgui.cpp:8809
IMGUI_API bool IsWindowChildOf(ImGuiWindow *window, ImGuiWindow *potential_parent)
Definition: imgui.cpp:5799
IMGUI_API void ChannelsSetCurrent(int channel_index)
Definition: imgui_draw.cpp:587
IMGUI_API void StyleColorsDark(ImGuiStyle *dst=NULL)
Definition: imgui_draw.cpp:171
IMGUI_API void PopItemFlag()
Definition: imgui.cpp:5581
void TranslateX(float dx)
void PathFillConvex(ImU32 col)
Definition: imgui.h:1843
IMGUI_API void appendf(const char *fmt,...) IM_FMTARGS(2)
Definition: imgui.cpp:2112
IMGUI_API bool OpenPopupOnItemClick(const char *str_id=NULL, int mouse_button=1)
Definition: imgui.cpp:6662
f
IMGUI_API void SetCursorPos(const ImVec2 &local_pos)
Definition: imgui.cpp:6212
ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
Definition: imgui.cpp:6979
bool ImTriangleContainsPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1229
IMGUI_API void SaveIniSettingsToDisk(const char *ini_filename)
Definition: imgui.cpp:8900
IMGUI_API void RenderTextClippedEx(ImDrawList *draw_list, const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, const ImVec2 *text_size_if_known, const ImVec2 &align=ImVec2(0, 0), const ImRect *clip_rect=NULL)
Definition: imgui.cpp:2268
IMGUI_API bool BeginPopupModal(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:6789
ImGuiID NavActivateId
IMGUI_API void LogRenderedText(const ImVec2 *ref_pos, const char *text, const char *text_end=NULL)
Definition: imgui.cpp:8634
int ImTextStrToUtf8(char *buf, int buf_size, const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1678
IMGUI_API const ImGuiPayload * AcceptDragDropPayload(const char *type, ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:8548
float FontWindowScale
IMGUI_API bool IsItemDeactivatedAfterEdit()
Definition: imgui.cpp:4153
T * GetByIndex(ImPoolIdx n)
int ImStrlenW(const ImWchar *str)
Definition: imgui.cpp:1312
Definition: imgui.h:164
IMGUI_API bool IsMouseClicked(int button, bool repeat=false)
Definition: imgui.cpp:4026
IMGUI_API bool IsItemClicked(int mouse_button=0)
Definition: imgui.cpp:4166
IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat=true)
Definition: imgui.cpp:3989
static void NavSaveLastChildNavWindow(ImGuiWindow *nav_window)
Definition: imgui.cpp:7270
float CurveTessellationTol
Definition: imgui.h:1256
ImVec2 GetBL() const
IMGUI_API void * GetVoidPtr(ImGuiID key) const
Definition: imgui.cpp:1882
ImVector< float > ItemWidthStack
int TooltipOverrideCount
IMGUI_API void PushMultiItemsWidths(int components, float width_full=0.0f)
Definition: imgui.cpp:5503
float MouseWheelH
Definition: imgui.h:1344
bool ActiveIdAllowOverlap
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding=0.0f)
Definition: imgui.cpp:2325
IMGUI_API void PopTextWrapPos()
Definition: imgui.cpp:5616
void push_back(const T &v)
Definition: imgui.h:1206
float ChildBorderSize
Definition: imgui.h:1233
ImVec2 DisplaySize
Definition: imgui.h:1277
bool IsLoaded() const
Definition: imgui.h:2101
IMGUI_API void CalcListClipping(int items_count, float items_height, int *out_items_display_start, int *out_items_display_end)
Definition: imgui.cpp:3856
static const float NAV_WINDOWING_LIST_APPEAR_DELAY
Definition: imgui.cpp:974
IMGUI_API bool IsMouseDown(int button)
Definition: imgui.cpp:4010
bool MouseClicked[5]
Definition: imgui.h:1383
IMGUI_API bool IsItemEdited()
Definition: imgui.cpp:4195
ImGuiWindow * Window
int FramerateSecPerFrameIdx
IMGUI_API void ClearFreeMemory()
Definition: imgui_draw.cpp:373
ImVec2 ItemSpacing
Definition: imgui.h:1239
IMGUI_API ImVec2 GetItemRectMin()
Definition: imgui.cpp:4211
IMGUI_API bool IsItemActive()
Definition: imgui.cpp:4135
void(* ImGuiSizeCallback)(ImGuiSizeCallbackData *data)
Definition: imgui.h:146
IMGUI_API ImGuiWindow * FindWindowByID(ImGuiID id)
Definition: imgui.cpp:4381
IMGUI_API void SetHoveredID(ImGuiID id)
Definition: imgui.cpp:2622
const char * ImStrchrRange(const char *str, const char *str_end, char c)
Definition: imgui.cpp:1306
ImGuiID HoveredId
bool Valid
Definition: imgui.h:1881
ImDrawList OverlayDrawList
static void UpdateMouseInputs()
Definition: imgui.cpp:3129
int FocusIdxAllRequestCurrent
IMGUI_API void SetNextWindowFocus()
Definition: imgui.cpp:6086
float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]
Definition: imgui.h:1394
IMGUI_API ImVec2 GetMouseDragDelta(int button=0, float lock_threshold=-1.0f)
Definition: imgui.cpp:4095
ImGuiNavMoveResult NavMoveResultLocal
static float OffsetNormToPixels(const ImGuiColumnsSet *columns, float offset_norm)
Definition: imgui.cpp:8041
bool IsInverted() const
float HoveredIdTimer
IMGUI_API void NewFrame()
Definition: imgui.cpp:3287
#define IMGUI_DEBUG_LOG(_FMT,...)
IMGUI_API void AddPolyline(const ImVec2 *points, const int num_points, ImU32 col, bool closed, float thickness)
Definition: imgui_draw.cpp:666
Count
ImVec2 LastValidMousePos
static void NavUpdateMoveResult()
Definition: imgui.cpp:7687
IMGUI_API void SetItemDefaultFocus()
Definition: imgui.cpp:6318
IMGUI_API void EndTooltip()
Definition: imgui.cpp:6559
static T ImClamp(T v, T mn, T mx)
ImVec1 BackupGroupOffset
IMGUI_API bool FocusableItemRegister(ImGuiWindow *window, ImGuiID id, bool tab_stop=true)
Definition: imgui.cpp:2830
XmlRpcServer s
ImVec2 DisplayPos
Definition: imgui.h:1886
IMGUI_API void LogButtons()
Definition: imgui.cpp:8756
int ImGuiFocusedFlags
Definition: imgui.h:137
bool MouseReleased[5]
Definition: imgui.h:1385
ImRect DragDropTargetRect
ImGuiWindow * RootWindowForNav
bool WantCollapseToggle
int ImGuiNavMoveFlags
ImVec2 ItemInnerSpacing
Definition: imgui.h:1240
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER
Definition: imgui.cpp:978
float FramerateSecPerFrameAccum
IMGUI_API void SetAllocatorFunctions(void *(*alloc_func)(size_t sz, void *user_data), void(*free_func)(void *ptr, void *user_data), void *user_data=NULL)
Definition: imgui.cpp:2949
IMGUI_API void PopAllowKeyboardFocus()
Definition: imgui.cpp:5594
IMGUI_API bool SmallButton(const char *label)
IMGUI_API bool IsMouseHoveringRect(const ImVec2 &r_min, const ImVec2 &r_max, bool clip=true)
Definition: imgui.cpp:3940
static void AddWindowToDrawDataSelectLayer(ImGuiWindow *window)
Definition: imgui.cpp:3631
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:2595
IMGUI_API void PushClipRect(const ImVec2 &clip_rect_min, const ImVec2 &clip_rect_max, bool intersect_with_current_clip_rect)
Definition: imgui.cpp:3675
IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value=true)
Definition: imgui.cpp:4130
IMGUI_API void BuildSortByKey()
Definition: imgui.cpp:1845
IMGUI_API bool BeginPopup(const char *str_id, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:6775
ImPool< ImGuiTabBar > TabBars
ImGuiSizeCallback SizeCallback
IMGUI_API void PathArcToFast(const ImVec2 &centre, float radius, int a_min_of_12, int a_max_of_12)
Definition: imgui_draw.cpp:935
IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow *window)
Definition: imgui.cpp:4512
IMGUI_API void ShowMetricsWindow(bool *p_open=NULL)
Definition: imgui.cpp:9112
IMGUI_API bool Draw(const char *label="Filter (inc,-exc)", float width=0.0f)
Definition: imgui.cpp:1984
IMGUI_API bool IsDragDropPayloadBeingAccepted()
Definition: imgui.cpp:8542
static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
Definition: imgui.cpp:7800
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow *window)
Definition: imgui.cpp:6863
static ImGuiWindow * CreateNewWindow(const char *name, ImVec2 size, ImGuiWindowFlags flags)
Definition: imgui.cpp:4393
ImVec2 PlatformImePos
ImGuiLayoutType LayoutType
int CmdListsCount
Definition: imgui.h:1883
ImVector< ImGuiItemFlags > ItemFlagsStack
IMGUI_API void BeginTooltip()
Definition: imgui.cpp:6519
IMGUI_API bool IsWindowAppearing()
Definition: imgui.cpp:6015
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
float KeysDownDuration[512]
Definition: imgui.h:1391
ImVec2 DisplayVisibleMax
Definition: imgui.h:1296
IMGUI_API void PushTextureID(ImTextureID texture_id)
Definition: imgui_draw.cpp:507
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2 &size_min, const ImVec2 &size_max, ImGuiSizeCallback custom_callback=NULL, void *custom_callback_data=NULL)
Definition: imgui.cpp:6062
IMGUI_API void * MemAlloc(size_t size)
Definition: imgui.cpp:2888
ImGuiDragDropFlags DragDropSourceFlags
static int IMGUI_CDECL ChildWindowComparer(const void *lhs, const void *rhs)
Definition: imgui.cpp:3557
bool FontAtlasOwnedByContext
ImGuiContext * GImGui
Definition: imgui.cpp:1042
IMGUI_API bool * GetBoolRef(ImGuiID key, bool default_val=false)
Definition: imgui.cpp:1899
ImGuiID SelectedTabId
ImVector< ImGuiTabItem > Tabs
static bool ImIsPowerOfTwo(int v)
void resize(int new_size)
Definition: imgui.h:1201
IMGUI_API void Indent(float indent_w=0.0f)
Definition: imgui.cpp:6499
T * end()
Definition: imgui.h:1192
#define IM_ARRAYSIZE(_ARR)
Definition: imgui.h:73
IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0)
Definition: imgui.cpp:5853
IMGUI_API void AddTriangleFilled(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col)
float BackupCurrentLineTextBaseOffset
ImVec2 SetWindowPosVal
void swap(ImVector< T > &rhs)
Definition: imgui.h:1198
IMGUI_API void PushButtonRepeat(bool repeat)
Definition: imgui.cpp:5599
ImRect TitleBarRect() const
static float ImFloor(float f)
ImGuiStorage StateStorage
ImVec2 MouseClickedPos[5]
Definition: imgui.h:1381
ImRect NavScoringRectScreen
bool IsDataType(const char *type) const
Definition: imgui.h:1466
IMGUI_API void ResetMouseDragDelta(int button=0)
Definition: imgui.cpp:4107
IMGUI_API float GetFloat(ImGuiID key, float default_val=0.0f) const
Definition: imgui.cpp:1874
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor=0.0f, float fast_factor=0.0f)
Definition: imgui.cpp:7371
IMGUI_API void AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners_flags=ImDrawCornerFlags_All, float thickness=1.0f)
IMGUI_API void SetCurrentFont(ImFont *font)
Definition: imgui.cpp:5538
bool MouseDoubleClicked[5]
Definition: imgui.h:1384
bool ActiveIdPreviousFrameIsAlive
ImVec2 DisplayVisibleMin
Definition: imgui.h:1295
int ImStricmp(const char *str1, const char *str2)
Definition: imgui.cpp:1264
char * ImStrdup(const char *str)
Definition: imgui.cpp:1285
static void CalcResizePosSizeFromAnyCorner(ImGuiWindow *window, const ImVec2 &corner_target, const ImVec2 &corner_norm, ImVec2 *out_pos, ImVec2 *out_size)
Definition: imgui.cpp:4566
ImFont * GetDefaultFont()
unsigned char DragDropPayloadBufLocal[8]
ImGuiInputReadMode
IMGUI_API ImGuiMouseCursor GetMouseCursor()
Definition: imgui.cpp:4115
int size() const
Definition: imgui.h:1580
static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)
Definition: imgui.cpp:4557
IMGUI_API float GetColumnOffset(int column_index=-1)
Definition: imgui.cpp:8070
const char * end() const
Definition: imgui.h:1560
IMGUI_API void SetScrollHereY(float center_y_ratio=0.5f)
Definition: imgui.cpp:6296
float CalcFontSize() const
ImGuiMenuColumns MenuColumns
int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1694
float WindowRounding
ImVec2 ImTriangleClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1248
IMGUI_API void UpdateHoveredWindowAndCaptureFlags()
Definition: imgui.cpp:3229
static ImGuiWindow * NavRestoreLastChildNavWindow(ImGuiWindow *window)
Definition: imgui.cpp:7280
static ImVec2 CalcSizeContents(ImGuiWindow *window)
Definition: imgui.cpp:4472
IMGUI_API void AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col, float thickness=1.0f)
ImGuiInputSource NavInputSource
IMGUI_API bool PassFilter(const char *text, const char *text_end=NULL) const
Definition: imgui.cpp:2035
static void SetWindowCollapsed(ImGuiWindow *window, bool collapsed, ImGuiCond cond)
Definition: imgui.cpp:5993
IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect=false)
Definition: imgui_draw.cpp:477
float FrameRounding
Definition: imgui.h:1237
int ImGuiItemFlags
float NavInputsDownDuration[ImGuiNavInput_COUNT]
Definition: imgui.h:1393
bool WantCaptureKeyboard
Definition: imgui.h:1362
IMGUI_API void SetNavID(ImGuiID id, int nav_layer)
Definition: imgui.cpp:2550
IMGUI_API void DestroyContext(ImGuiContext *ctx=NULL)
Definition: imgui.cpp:2965
IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags=0)
Definition: imgui.cpp:2757
ImVector< ImFont * > Fonts
Definition: imgui.h:2059
IMGUI_API ImVec2 GetItemRectSize()
Definition: imgui.cpp:4223
IMGUI_API float GetWindowScrollMaxY(ImGuiWindow *window)
Definition: imgui.cpp:4523
IMGUI_API float GetWindowWidth()
Definition: imgui.cpp:5882
IMGUI_API void ** GetVoidPtrRef(ImGuiID key, void *default_val=NULL)
Definition: imgui.cpp:1912
IMGUI_API bool IsAnyItemFocused()
Definition: imgui.cpp:4183
static void * MallocWrapper(size_t size, void *user_data)
Definition: imgui.cpp:1049
ImVector< ImGuiColorMod > ColorModifiers
float HoveredIdNotActiveTimer
IMGUI_API void Build()
Definition: imgui.cpp:2014
IMGUI_API bool TreeNode(const char *label)
IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
Definition: imgui.cpp:7349
IMGUI_API ImVec2 GetContentRegionMax()
Definition: imgui.cpp:6100
ImVector< ImGuiWindow * > CurrentWindowStack
static T ImLerp(T a, T b, float t)
ImVector< char > Buf
Definition: imgui.h:1573
static const char * GetFallbackWindowNameForWindowingList(ImGuiWindow *window)
Definition: imgui.cpp:7952
ImVector< Pair > Data
Definition: imgui.h:1607
int ImGuiDragDropFlags
Definition: imgui.h:136
int KeyMap[ImGuiKey_COUNT]
Definition: imgui.h:1285
geometry_msgs::TransformStamped t
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2 &size, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4339
IMGUI_API void ClearInputCharacters()
Definition: imgui.cpp:1207
ImVector< ImFont * > FontStack
ImVec2 uv
Definition: imgui.h:1742
void(* ImeSetInputScreenPosFn)(int x, int y)
Definition: imgui.h:1325
ImGuiID NavActivatePressedId
doubleAcc dot(const VectorAcc &lhs, const VectorAcc &rhs)
IMGUI_API void ActivateItem(ImGuiID id)
Definition: imgui.cpp:6304
IMGUI_API void SetWindowPos(const ImVec2 &pos, ImGuiCond cond=0)
Definition: imgui.cpp:5932
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow *window, bool snap_on_edges)
Definition: imgui.cpp:4528
IMGUI_API ImGuiTextFilter(const char *default_filter="")
Definition: imgui.cpp:1970
float ColumnsMinSpacing
Definition: imgui.h:1243
float DeltaTime
Definition: imgui.h:1278
bool WantCaptureMouse
Definition: imgui.h:1361
static bool IsWindowActiveAndVisible(ImGuiWindow *window)
Definition: imgui.cpp:3124
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2 &ref_pos, const ImVec2 &size, ImGuiDir *last_dir, const ImRect &r_outer, const ImRect &r_avoid, ImGuiPopupPositionPolicy policy=ImGuiPopupPositionPolicy_Default)
Definition: imgui.cpp:6873
GLenum GLuint id
Definition: gl.h:1033
IMGUI_API void MemFree(void *ptr)
Definition: imgui.cpp:2895
IMGUI_API void Clear()
Definition: imgui_draw.cpp:356
unsigned short ImDrawIdx
Definition: imgui.h:1734
IMGUI_API bool IsMousePosValid(const ImVec2 *mouse_pos=NULL)
Definition: imgui.cpp:4084
ImGuiNavMoveFlags NavMoveRequestFlags
ImGuiItemFlags ItemFlags
IMGUI_API void SetStateStorage(ImGuiStorage *storage)
Definition: imgui.cpp:6335
IMGUI_API void FlattenIntoSingleLayer()
Definition: imgui.cpp:3640
IMGUI_API ImVec2 GetMousePos()
Definition: imgui.cpp:4069
IMGUI_API bool BeginDragDropTargetCustom(const ImRect &bb, ImGuiID id)
Definition: imgui.cpp:8490
ImDrawList * DrawList
ImVec2 SetWindowPosPivot
ImDrawDataBuilder DrawDataBuilder
IMGUI_API ImGuiWindowSettings * CreateNewWindowSettings(const char *name)
Definition: imgui.cpp:8799
IMGUI_API ImGuiID GetHoveredID()
Definition: imgui.cpp:2631
ImGuiWindow(ImGuiContext *context, const char *name)
Definition: imgui.cpp:2434
unsigned short ImWchar
Definition: imgui.h:119
bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode)
static ImVec2 CalcSizeAutoFit(ImGuiWindow *window, const ImVec2 &size_contents)
Definition: imgui.cpp:4485
int ImGuiCond
Definition: imgui.h:121
bool NavActive
Definition: imgui.h:1366
IMGUI_API float GetWindowScrollMaxX(ImGuiWindow *window)
Definition: imgui.cpp:4518
ImGuiDataType Type
Definition: imgui.cpp:5658
IMGUI_API void EndDragDropSource()
Definition: imgui.cpp:8431
ImGuiID GetIDNoKeepAlive(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2520
void Clear()
Definition: imgui.h:1892
ImGuiID ActiveId
int ImGuiDir
Definition: imgui.h:123
IMGUI_API void EndDragDropTarget()
Definition: imgui.cpp:8598
IMGUI_API void SetMouseCursor(ImGuiMouseCursor type)
Definition: imgui.cpp:4120
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow *window)
Definition: imgui.cpp:6926
IMGUI_API ImVec2 GetContentRegionAvail()
Definition: imgui.cpp:6109
ImVec2 BackupCurrentLineSize
ImGuiDir NavMoveClipDir
ImGuiID GetIDFromRectangle(const ImRect &r_abs)
Definition: imgui.cpp:2533
const char * begin() const
Definition: imgui.h:1559
ImGuiLayoutType ParentLayoutType
static void NavProcessItem(ImGuiWindow *window, const ImRect &nav_bb, const ImGuiID id)
Definition: imgui.cpp:7142
void * ImFileLoadToMemory(const char *filename, const char *file_open_mode, size_t *out_file_size, int padding_bytes)
Definition: imgui.cpp:1485
IMGUI_API void SetFloat(ImGuiID key, float val)
Definition: imgui.cpp:1937
static void NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect &r, const ImRect &clip_rect)
Definition: imgui.cpp:6995
IMGUI_API float GetScrollMaxY()
Definition: imgui.cpp:6267
IMGUI_API void SetCurrentContext(ImGuiContext *ctx)
Definition: imgui.cpp:2926
static const float NAV_WINDOWING_HIGHLIGHT_DELAY
Definition: imgui.cpp:973
IMGUI_API void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f)
Definition: imgui.cpp:2338
ImFontAtlas * ContainerAtlas
Definition: imgui.h:2087
IMGUI_API ImDrawList * GetWindowDrawList()
Definition: imgui.cpp:6163
ImGuiWindow * NavLastChildNavWindow
ImVector< ImGuiWindow * > Windows
int ImTextCountUtf8BytesFromChar(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1663
IMGUI_API bool Begin(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4736
#define IM_ASSERT(_EXPR)
Definition: imgui.h:64
void pop_back()
Definition: imgui.h:1207
int WantTextInputNextFrame
bool NavWindowingToggleLayer
int ImGuiWindowFlags
Definition: imgui.h:144
IMGUI_API bool IsKeyDown(int user_key_index)
Definition: imgui.cpp:3963
IMGUI_API void PopStyleVar(int count=1)
Definition: imgui.cpp:5725
static void SetClipboardTextFn_DefaultImpl(void *user_data, const char *text)
Definition: imgui.cpp:9067
int DataFrameCount
Definition: imgui.h:1459
IMGUI_API void SetScrollY(float scroll_y)
Definition: imgui.cpp:6279
ImVec2 MouseDragMaxDistanceAbs[5]
Definition: imgui.h:1389
float FontSize
Definition: imgui.h:2074
ImVec2 GetSize() const
ImVec2 SizeContentsExplicit
ImGuiNavForward NavMoveRequestForward
float Alpha
Definition: imgui.h:1226
IMGUI_API void SetTooltipV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui.cpp:6565
ImGuiID GetID(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2504
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:3827
static void CheckStacksSize(ImGuiWindow *window, bool write)
Definition: imgui.cpp:4359
#define IM_COL32_A_SHIFT
Definition: imgui.h:1679
IMGUI_API ImVec2 GetWindowContentRegionMin()
Definition: imgui.cpp:6121
IMGUI_API bool BeginPopupContextWindow(const char *str_id=NULL, int mouse_button=1, bool also_over_items=true)
Definition: imgui.cpp:6842
IMGUI_API void KeepAliveID(ImGuiID id)
Definition: imgui.cpp:2637
void Expand(const float amount)
IMGUI_API void BulletText(const char *fmt,...) IM_FMTARGS(1)
ImVector< ImWchar > InputQueueCharacters
Definition: imgui.h:1395
int MetricsActiveAllocations
Definition: imgui.h:1373
IMGUI_API bool IsAnyItemHovered()
Definition: imgui.cpp:4171
ImGuiInputTextState InputTextState
static void SetWindowSize(ImGuiWindow *window, const ImVec2 &size, ImGuiCond cond)
Definition: imgui.cpp:5950
static void UpdateMouseWheel()
Definition: imgui.cpp:3183
int ImTextStrFromUtf8(ImWchar *buf, int buf_size, const char *in_text, const char *in_text_end, const char **in_text_remaining)
Definition: imgui.cpp:1590
const char * ImStristr(const char *haystack, const char *haystack_end, const char *needle, const char *needle_end)
Definition: imgui.cpp:1334
ImGuiID OpenParentId
float w
Definition: imgui.h:178
static void ImSwap(T &a, T &b)
IMGUI_API const char * GetStyleColorName(ImGuiCol idx)
Definition: imgui.cpp:5741
IMGUI_API bool IsMouseDragging(int button=0, float lock_threshold=-1.0f)
Definition: imgui.cpp:4058
IMGUI_API bool BeginChild(const char *str_id, const ImVec2 &size=ImVec2(0, 0), bool border=false, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4287
int DisplayStart
Definition: imgui.h:1655
#define IM_F32_TO_INT8_SAT(_VAL)
static float ImLengthSqr(const ImVec2 &lhs)
IMGUI_API ImVec2 GetWindowContentRegionMax()
Definition: imgui.cpp:6127
IMGUI_API int GetInt(ImGuiID key, int default_val=0) const
Definition: imgui.cpp:1861
bool NavInitRequestFromMove
IMGUI_API bool IsRectVisible(const ImVec2 &size)
Definition: imgui.cpp:6393
ImGuiColumnsFlags Flags
IMGUI_API bool Step()
Definition: imgui.cpp:2168
void ClipWith(const ImRect &r)
ImVec2 SizeFullAtLastBegin
IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio=0.5f)
Definition: imgui.cpp:6286
ImVec2 WindowMinSize
Definition: imgui.h:1230
ImGuiNavLayer
ImGuiID NavJustTabbedId
bool Preview
Definition: imgui.h:1461
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled)
Definition: imgui.cpp:5571
ImGuiWindow * NavWindowingTargetAnim
ImGuiWindow * RootWindow
ImU32 ImHash(const void *data, int data_size, ImU32 seed)
Definition: imgui.cpp:1425
float MouseDownDuration[5]
Definition: imgui.h:1387
ImGuiNavLayer NavLayer
IMGUI_API void Scrollbar(ImGuiLayoutType direction)
IMGUI_API void SetColumnOffset(int column_index, float offset_x)
Definition: imgui.cpp:8109
ImVec2 Max
IMGUI_API void Unindent(float indent_w=0.0f)
Definition: imgui.cpp:6507
void push_front(const T &v)
Definition: imgui.h:1208
const char * _OwnerName
Definition: imgui.h:1797
T * Data
Definition: imgui.h:1170
bool BackupActiveIdPreviousFrameIsAlive
IMGUI_API int GetColumnsCount()
Definition: imgui.cpp:8035
#define IM_COL32(R, G, B, A)
Definition: imgui.h:1682
#define IM_COL32_B_SHIFT
Definition: imgui.h:1678
static float ImFabs(float x)
float ItemWidthDefault
IMGUI_API void FocusWindow(ImGuiWindow *window)
Definition: imgui.cpp:5444
ImVector< ImDrawCmd > CmdBuffer
Definition: imgui.h:1790
ImGuiWindow * ActiveIdWindow
ImGuiTextBuffer SettingsIniData
float NavWindowingTimer
float ChildRounding
Definition: imgui.h:1232
ImGuiWindow * NavWindowingTarget
ImVector< ImGuiStyleMod > StyleModifiers
IMGUI_API void RenderNavHighlight(const ImRect &bb, ImGuiID id, ImGuiNavHighlightFlags flags=ImGuiNavHighlightFlags_TypeDefault)
Definition: imgui.cpp:2397
IMGUI_API void AddText(const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end=NULL)
ImGuiDir AutoPosLastDirection
void * ClipboardUserData
Definition: imgui.h:1321
ImRect ContentsRegionRect
int ImGuiStyleVar
Definition: imgui.h:127
ImDrawListSharedData DrawListSharedData
ImGuiID HoveredIdPreviousFrame
IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup()
Definition: imgui.cpp:4075
IMGUI_API bool ItemAdd(const ImRect &bb, ImGuiID id, const ImRect *nav_bb=NULL)
Definition: imgui.cpp:2714
float MouseDoubleClickTime
Definition: imgui.h:1282
ImGuiID DragDropTargetId
ImGuiID SourceId
Definition: imgui.h:1457
float KeysDownDurationPrev[512]
Definition: imgui.h:1392
IMGUI_API ImGuiIO & GetIO()
Definition: imgui.cpp:2975
void ImTriangleBarycentricCoords(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p, float &out_u, float &out_v, float &out_w)
Definition: imgui.cpp:1237
ImVector< ImGuiColumnData > Columns
int ImGuiKey
Definition: imgui.h:124
int MetricsRenderIndices
Definition: imgui.h:1370
int DataSize
Definition: imgui.h:1454
static T ImMax(T lhs, T rhs)
IMGUI_API void Shutdown(ImGuiContext *context)
Definition: imgui.cpp:3491
IMGUI_API ImGuiWindow * GetFrontMostPopupModal()
Definition: imgui.cpp:6600
float z
Definition: imgui.h:178
int ImGuiNavDirSourceFlags
ImVec2 WindowPadding
IMGUI_API ImFont * GetFont()
Definition: imgui.cpp:6169
const char * c_str() const
Definition: imgui.h:1584
#define ImQsort
bool FrameScopePushedImplicitWindow
IMGUI_API void EndGroup()
Definition: imgui.cpp:6431
static int ImTextCharToUtf8(char *buf, int buf_size, unsigned int c)
Definition: imgui.cpp:1625
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow *window)
Definition: imgui.cpp:5877
ImGuiID NavInitResultId
bool KeysDown[512]
Definition: imgui.h:1349
IMGUI_API int GetColumnIndex()
Definition: imgui.cpp:8029
#define IM_COL32_A_MASK
Definition: imgui.h:1680
IMGUI_API bool IsItemDeactivated()
Definition: imgui.cpp:4146
IMGUI_API void ChannelsMerge()
Definition: imgui_draw.cpp:553
IMGUI_API bool IsKeyReleased(int user_key_index)
Definition: imgui.cpp:4002
IMGUI_API void LogToFile(int max_depth=-1, const char *filename=NULL)
Definition: imgui.cpp:8689
ImGuiID ActiveIdPreviousFrame
short BeginOrderWithinParent
IMGUI_API ImGuiContext * GetCurrentContext()
Definition: imgui.cpp:2921
void ImStrncpy(char *dst, const char *src, size_t count)
Definition: imgui.cpp:1278
IMGUI_API void SetWindowFocus()
Definition: imgui.cpp:6027
ImVector< ImGuiWindow * > WindowsFocusOrder
IMGUI_API bool IsWindowCollapsed()
Definition: imgui.cpp:6009
IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect &rect_rel)
Definition: imgui.cpp:2559
static int FindWindowFocusIndex(ImGuiWindow *window)
Definition: imgui.cpp:7782
IMGUI_API void Initialize(ImGuiContext *context)
Definition: imgui.cpp:3473
IMGUI_API float GetContentRegionAvailWidth()
Definition: imgui.cpp:6115
#define IMGUI_VERSION
Definition: imgui.h:48
unsigned int ImGuiID
Definition: imgui.h:118
bool KeyShift
Definition: imgui.h:1346
int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1609
float PopupBorderSize
Definition: imgui.h:1235
ImVector< ImGuiWindowSettings > SettingsWindows
IMGUI_API void PushItemWidth(float item_width)
Definition: imgui.cpp:5496
IMGUI_API ImGuiContext * CreateContext(ImFontAtlas *shared_font_atlas=NULL)
Definition: imgui.cpp:2956
IMGUI_API void StartMouseMovingWindow(ImGuiWindow *window)
Definition: imgui.cpp:3020
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0))
ImVec2 ScrollTargetCenterRatio
ImU32 col
Definition: imgui.h:1743
IMGUI_API void MarkItemEdited(ImGuiID id)
Definition: imgui.cpp:2646
T & back()
Definition: imgui.h:1196
IMGUI_API bool IsItemFocused()
Definition: imgui.cpp:4159
ImGuiWindow * HoveredRootWindow
int FocusIdxTabRequestCurrent
IMGUI_API void Separator()
#define IM_NEWLINE
Definition: imgui_demo.cpp:90
IMGUI_API void End()
Definition: imgui.cpp:5371
ImGuiID LastActiveId
bool ConfigWindowsMoveFromTitleBarOnly
Definition: imgui.h:1303
IMGUI_API void FocusableItemUnregister(ImGuiWindow *window)
Definition: imgui.cpp:2855
IMGUI_API void ItemSize(const ImVec2 &size, float text_offset_y=0.0f)
Definition: imgui.cpp:2679
Definition: imgui.h:176
ImGuiWindow * MovingWindow
IMGUI_API void BeginGroup()
Definition: imgui.cpp:6406
int Size
Definition: imgui.h:1168
bool FontAllowUserScaling
Definition: imgui.h:1292
IMGUI_API void AddCircleFilled(const ImVec2 &centre, float radius, ImU32 col, int num_segments=12)
char DataType[32+1]
Definition: imgui.h:1460
const ImWchar * ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin)
Definition: imgui.cpp:1327
IMGUI_API float GetScrollX()
Definition: imgui.cpp:6252
IMGUI_API void Begin(int items_count, float items_height=-1.0f)
Definition: imgui.cpp:2141
ImTextureID TexID
Definition: imgui.h:2047
ImGuiID ScalarAsInputTextId
bool MouseDown[5]
Definition: imgui.h:1342
IMGUI_API void BringWindowToFocusFront(ImGuiWindow *window)
Definition: imgui.cpp:5400
IMGUI_API const ImGuiPayload * GetDragDropPayload()
Definition: imgui.cpp:8591
static void SettingsHandlerWindow_WriteAll(ImGuiContext *imgui_ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf)
Definition: imgui.cpp:8951
ImGuiTextBuffer LogClipboard
#define va_copy(dest, src)
Definition: imgui.cpp:2079
IMGUI_API bool BeginPopupContextVoid(const char *str_id=NULL, int mouse_button=1)
Definition: imgui.cpp:6853
IMGUI_API void SetCursorPosX(float local_x)
Definition: imgui.cpp:6219
float DragDropAcceptIdCurrRectSurface
int ImGuiHoveredFlags
Definition: imgui.h:138
unsigned int _VtxCurrentIdx
Definition: imgui.h:1798
int ImGuiMouseCursor
Definition: imgui.h:126
IMGUI_API void SameLine(float local_pos_x=0.0f, float spacing_w=-1.0f)
Definition: imgui.cpp:6476
IMGUI_API float GetColumnWidth(int column_index=-1)
Definition: imgui.cpp:8098
int ImFormatStringV(char *buf, size_t buf_size, const char *fmt, va_list args)
Definition: imgui.cpp:1405
IMGUI_API ImVec2 GetWindowSize()
Definition: imgui.cpp:5944
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow *window)
Definition: imgui.cpp:5429
IMGUI_API void EndPopup()
Definition: imgui.cpp:6817
int MetricsRenderWindows
Definition: imgui.h:1371
int HiddenFramesForResize
ImVec2 ImLineClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &p)
Definition: imgui.cpp:1216
void TranslateY(float dy)
ImGuiWindow * NavWindowingList
bool KeyCtrl
Definition: imgui.h:1345
IMGUI_API ImVec2 GetFontTexUvWhitePixel()
Definition: imgui.cpp:6179
ImGuiWindow * ParentWindow
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width)
Definition: imgui.cpp:2250
short BeginOrderWithinContext
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2 &pos)
static bool ImCharIsBlankA(char c)
IMGUI_API void ClearDragDrop()
Definition: imgui.cpp:8317
IMGUI_API void TextV(const char *fmt, va_list args) IM_FMTLIST(1)
IMGUI_API void RenderBullet(ImVec2 pos)
Definition: imgui.cpp:2372
bool empty() const
Definition: imgui.h:1183
IMGUI_API void NextColumn()
Definition: imgui.cpp:7995
float x
Definition: imgui.h:178
static float GetColumnWidthEx(ImGuiColumnsSet *columns, int column_index, bool before_resize=false)
Definition: imgui.cpp:8085
ImVector< ImGuiPopupRef > OpenPopupStack
ImRect InnerClipRect
const char * begin() const
Definition: imgui.h:1578
bool MouseDownOwned[5]
Definition: imgui.h:1386
float IndentSpacing
Definition: imgui.h:1242
ImGuiID BackupActiveIdIsAlive
IMGUI_API float GetWindowHeight()
Definition: imgui.cpp:5888
ImGuiID DragDropAcceptIdPrev
ImVector< char > PrivateClipboard
int ImDrawListFlags
Definition: imgui.h:129
static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS
Definition: imgui.cpp:977
float LastActiveIdTimer
IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4 &in)
Definition: imgui.cpp:1723
ImVec2 DisplaySafeAreaPadding
Definition: imgui.h:1252
ImGuiCond SetWindowCollapsedAllowFlags
IMGUI_API void AddInputCharactersUTF8(const char *str)
Definition: imgui.cpp:1196
IMGUI_API void BeginColumns(const char *str_id, int count, ImGuiColumnsFlags flags=0)
Definition: imgui.cpp:8164
typedef void(GLAD_API_PTR *GLDEBUGPROC)(GLenum source
IMGUI_API void AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners_flags=ImDrawCornerFlags_All)
IMGUI_API void PushFont(ImFont *font)
Definition: imgui.cpp:5553
static ImGuiWindow * FindWindowNavFocusable(int i_start, int i_stop, int dir)
Definition: imgui.cpp:7791
bool Locked
Definition: imgui.h:2045
float SettingsDirtyTimer
ImGuiWindow * CurrentWindow
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiCond cond=0, const ImVec2 &pivot=ImVec2(0, 0))
Definition: imgui.cpp:6045
ImVec2 DisplayWindowPadding
Definition: imgui.h:1251
IMGUI_API void SetClipboardText(const char *text)
Definition: imgui.cpp:2908
ImVec2 GetTR() const
float IniSavingRate
Definition: imgui.h:1279
float y
Definition: imgui.h:166
IMGUI_API void SetBool(ImGuiID key, bool val)
Definition: imgui.cpp:1932
ImGuiStyle Style
int MetricsRenderVertices
Definition: imgui.h:1369
IMGUI_API void appendfv(const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui.cpp:2086
IMGUI_API void EndChild()
Definition: imgui.cpp:4299
void Update(int count, float spacing, bool clear)
IMGUI_API float GetWindowContentRegionWidth()
Definition: imgui.cpp:6133
IMGUI_API float GetScrollMaxX()
Definition: imgui.cpp:6262
ImDrawListFlags Flags
Definition: imgui.h:1793
ImRect InnerMainRect
ImVec2 FramePadding
Definition: imgui.h:1236
int DragDropAcceptFrameCount
IMGUI_API float GetTextLineHeightWithSpacing()
Definition: imgui.cpp:6145
IMGUI_API void FocusPreviousWindowIgnoringOne(ImGuiWindow *ignore_window)
Definition: imgui.cpp:5479
int ImStrnicmp(const char *str1, const char *str2, size_t count)
Definition: imgui.cpp:1271
int LogAutoExpandMaxDepth
IMGUI_API void TextColored(const ImVec4 &col, const char *fmt,...) IM_FMTARGS(2)
float FramerateSecPerFrame[120]
bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode)
ImVec4 Colors[ImGuiCol_COUNT]
Definition: imgui.h:1257
IMGUI_API bool SliderInt(const char *label, int *v, int v_min, int v_max, const char *format="%d")
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border=true, float rounding=0.0f)
Definition: imgui.cpp:2312
ImGuiWindowFlags Flags
void clear()
Definition: imgui.h:1189
IMGUI_API float CalcItemWidth()
Definition: imgui.cpp:5524
IMGUI_API void SetInt(ImGuiID key, int val)
Definition: imgui.cpp:1921
ImDrawCallback UserCallback
Definition: imgui.h:1726
int TotalIdxCount
Definition: imgui.h:1884
IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate)
Definition: imgui.cpp:3980
IMGUI_API void Text(const char *fmt,...) IM_FMTARGS(1)
IMGUI_API void LogToTTY(int max_depth=-1)
Definition: imgui.cpp:8673
float MouseDoubleClickMaxDist
Definition: imgui.h:1283
#define IM_COL32_G_SHIFT
Definition: imgui.h:1677
ImDrawVert * _VtxWritePtr
Definition: imgui.h:1799
ImGuiBackendFlags BackendFlags
Definition: imgui.h:1276
float FontGlobalScale
Definition: imgui.h:1291
IMGUI_API ImVec2 GetCursorScreenPos()
Definition: imgui.cpp:6239
IMGUI_API ImGuiWindow * FindWindowByName(const char *name)
Definition: imgui.cpp:4387
IMGUI_API void NavMoveRequestCancel()
Definition: imgui.cpp:7216
bool NavDisableHighlight
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x=0.0f)
Definition: imgui.cpp:5609
static float GetDraggedColumnOffset(ImGuiColumnsSet *columns, int column_index)
Definition: imgui.cpp:8053
ImDrawList DrawListInst
static void NavUpdateAnyRequestFlag()
Definition: imgui.cpp:7297
void(* RenderDrawListsFn)(ImDrawData *data)
Definition: imgui.h:1331
IMGUI_API void EndChildFrame()
Definition: imgui.cpp:4353
IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:8333
IMGUI_API ImGuiStyle()
Definition: imgui.cpp:1064
IMGUI_API void OpenPopupEx(ImGuiID id)
Definition: imgui.cpp:6620
ImGuiDragDropFlags DragDropAcceptFlags
IMGUI_API bool NavMoveRequestButNoResultYet()
Definition: imgui.cpp:7210
IMGUI_API void UpdateMouseMovingWindowEndFrame()
Definition: imgui.cpp:3075
ImVector< ImGuiWindow * > WindowsSortBuffer
IMGUI_API void PopItemWidth()
Definition: imgui.cpp:5517
ImVector< ImGuiSettingsHandler > SettingsHandlers
static ImRect GetViewportRect()
Definition: imgui.cpp:4229
IMGUI_API void SetNextWindowBgAlpha(float alpha)
Definition: imgui.cpp:6092
float KeyRepeatDelay
Definition: imgui.h:1286
ImVector< float > TextWrapPosStack
static void SetWindowConditionAllowFlags(ImGuiWindow *window, ImGuiCond flags, bool enabled)
Definition: imgui.cpp:4374
IMGUI_API void TreePop()
IMGUI_API void SetWindowScrollY(ImGuiWindow *window, float new_scroll_y)
Definition: imgui.cpp:5908
ImGuiDir NavMoveDir
float MouseDragThreshold
Definition: imgui.h:1284
static void AddDrawListToDrawData(ImVector< ImDrawList *> *out_list, ImDrawList *draw_list)
Definition: imgui.cpp:3585
static char EmptyString[1]
Definition: imgui.h:1574
int TotalVtxCount
Definition: imgui.h:1885
IMGUI_API void ScaleAllSizes(float scale_factor)
Definition: imgui.cpp:1104
ImVector< char > InitialText
static void SetupDrawData(ImVector< ImDrawList *> *draw_lists, ImDrawData *draw_data)
Definition: imgui.cpp:3658
ImGuiNavMoveResult NavMoveResultOther
IMGUI_API ImDrawList * GetOverlayDrawList()
Definition: imgui.cpp:3010
static bool IsWindowContentHoverable(ImGuiWindow *window, ImGuiHoveredFlags flags)
Definition: imgui.cpp:2658
bool empty() const
Definition: imgui.h:1561
ImVec2 MousePosPrev
Definition: imgui.h:1380
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip=true)
Definition: imgui.cpp:6541
int ImGuiDataType
Definition: imgui.h:122
ImVec2 TexUvWhitePixel
Definition: imgui.h:2058
IMGUI_API void EndColumns()
Definition: imgui.cpp:8228
ImGuiWindow * ActiveIdPreviousFrameWindow
int FocusIdxAllRequestNext
bool AntiAliasedLines
Definition: imgui.h:1254
static void SetCurrentWindow(ImGuiWindow *window)
Definition: imgui.cpp:2542
ImVec2 ScrollbarSizes
IMGUI_API void LogText(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:8617
IMGUI_API bool IsItemVisible()
Definition: imgui.cpp:4189
static void NavScrollToBringItemIntoView(ImGuiWindow *window, const ImRect &item_rect)
Definition: imgui.cpp:7389
IMGUI_API double GetTime()
Definition: imgui.cpp:2994
IMGUI_API int * GetIntRef(ImGuiID key, int default_val=0)
Definition: imgui.cpp:1891
static float ImSaturate(float f)
IMGUI_API bool ButtonBehavior(const ImRect &bb, ImGuiID id, bool *out_hovered, bool *out_held, ImGuiButtonFlags flags=0)
void ClipWithFull(const ImRect &r)
IMGUI_API bool BeginDragDropTarget()
Definition: imgui.cpp:8516
Definition: imgui.h:2071
static const ImGuiStyleVarInfo GStyleVarInfo[]
Definition: imgui.cpp:5664
IMGUI_API void EndFrame()
Definition: imgui.cpp:3690
IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)
Definition: imgui.cpp:3970
IMGUI_API float GetTextLineHeight()
Definition: imgui.cpp:6139
static void AddWindowToDrawData(ImVector< ImDrawList *> *out_list, ImGuiWindow *window)
Definition: imgui.cpp:3618
ImGuiID NavActivateDownId
IMGUI_API bool ItemHoverable(const ImRect &bb, ImGuiID id)
Definition: imgui.cpp:2797
IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col)
Definition: imgui.cpp:5624
ImVector< ImDrawList * > Layers[2]
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
Definition: imgui.cpp:9104
bool Delivery
Definition: imgui.h:1462
void * Data
Definition: imgui.h:1453
ImGuiConfigFlags ConfigFlags
Definition: imgui.h:1275
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:2569
ImGuiWindow * NavWindow
#define IM_OFFSETOF(_TYPE, _MEMBER)
Definition: imgui.h:74
ImVec2 GetBR() const
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2 &pos, float radius)
void PathLineTo(const ImVec2 &pos)
Definition: imgui.h:1841
static void NavUpdate()
Definition: imgui.cpp:7419
ImVector< ImGuiPopupRef > BeginPopupStack
void IM_DELETE(T *p)
Definition: imgui.h:1525
void *(* ReadOpenFn)(ImGuiContext *ctx, ImGuiSettingsHandler *handler, const char *name)
IMGUI_API int GetFrameCount()
Definition: imgui.cpp:2999
float FrameBorderSize
Definition: imgui.h:1238
IMGUI_API void End()
Definition: imgui.cpp:2157
bool HoveredIdAllowOverlap
void * ImeWindowHandle
Definition: imgui.h:1326
float BackupFloat[2]
int WantCaptureKeyboardNextFrame
IMGUI_API const char * GetClipboardText()
Definition: imgui.cpp:2903
IMGUI_API bool Selectable(const char *label, bool selected=false, ImGuiSelectableFlags flags=0, const ImVec2 &size=ImVec2(0, 0))
bool NavMoveFromClampedRefRect
IMGUI_API void SetNextWindowContentSize(const ImVec2 &size)
Definition: imgui.cpp:6071
int index_from_ptr(const T *it) const
Definition: imgui.h:1214
IMGUI_API ImGuiIO()
Definition: imgui.cpp:1128
static void * GImAllocatorUserData
Definition: imgui.cpp:1058
IMGUI_API void NavInitWindow(ImGuiWindow *window, bool force_reinit)
Definition: imgui.cpp:7306
IMGUI_API int GetKeyIndex(ImGuiKey imgui_key)
Definition: imgui.cpp:3956
IMGUI_API void PopButtonRepeat()
Definition: imgui.cpp:5604
bool WantTextInput
Definition: imgui.h:1363
IMGUI_API bool Checkbox(const char *label, bool *v)
IMGUI_API void SetWindowScrollX(ImGuiWindow *window, float new_scroll_x)
Definition: imgui.cpp:5901
ImVector< ImDrawVert > VtxBuffer
Definition: imgui.h:1792
static void * SettingsHandlerWindow_ReadOpen(ImGuiContext *, ImGuiSettingsHandler *, const char *name)
Definition: imgui.cpp:8933
static float ImFmod(float x, float y)
IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond=0)
Definition: imgui.cpp:6078
ImVec2 WindowTitleAlign
Definition: imgui.h:1231
IMGUI_API void LoadIniSettingsFromDisk(const char *ini_filename)
Definition: imgui.cpp:8818
#define IM_COL32_R_SHIFT
Definition: imgui.h:1676
IMGUI_API float CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x)
Definition: imgui.cpp:2874
ImVector< ImGuiGroupData > GroupStack
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]
ImVec2 MouseDelta
Definition: imgui.h:1374
IMGUI_API ImVec2 GetItemRectMax()
Definition: imgui.cpp:4217
unsigned int ElemCount
Definition: imgui.h:1723
const ImGuiResizeGripDef resize_grip_def[4]
Definition: imgui.cpp:4587
ImVector< ImGuiColumnsSet > ColumnsStorage
float MouseDragMaxDistanceSqr[5]
Definition: imgui.h:1390
IMGUI_API float GetScrollY()
Definition: imgui.cpp:6257
IMGUI_API void SetCursorScreenPos(const ImVec2 &pos)
Definition: imgui.cpp:6245
ImGuiPayload DragDropPayload
int MetricsActiveWindows
Definition: imgui.h:1372
ImVec2 DisplayFramebufferScale
Definition: imgui.h:1294
IMGUI_API void LogToClipboard(int max_depth=-1)
Definition: imgui.cpp:8717
static float PixelsToOffsetNorm(const ImGuiColumnsSet *columns, float offset)
Definition: imgui.cpp:8046
IMGUI_API void TabBarQueueChangeTabOrder(ImGuiTabBar *tab_bar, const ImGuiTabItem *tab, int dir)
void clear()
Definition: imgui.h:1582
static ImGuiStorage::Pair * LowerBound(ImVector< ImGuiStorage::Pair > &data, ImGuiID key)
Definition: imgui.cpp:1822
ImRect NavRectRel[ImGuiNavLayer_COUNT]
IMGUI_API const char * GetVersion()
Definition: imgui.cpp:2914
float MouseWheel
Definition: imgui.h:1343
IMGUI_API float GetFrameHeight()
Definition: imgui.cpp:6151
ImGuiID SourceParentId
Definition: imgui.h:1458
static void NavUpdateWindowingList()
Definition: imgui.cpp:7962
ImGuiItemStatusFlags LastItemStatusFlags
IMGUI_API void PushID(const char *str_id)
Definition: imgui.cpp:6347
bool ActiveIdHasBeenEdited
IMGUI_API ImGuiID GetID(const char *str_id)
Definition: imgui.cpp:6378
bool KeyAlt
Definition: imgui.h:1347
IMGUI_API void SetCursorPosY(float local_y)
Definition: imgui.cpp:6226
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus)
Definition: imgui.cpp:5589
IMGUI_API void split(char separator, ImVector< TextRange > *out) const
Definition: imgui.cpp:1996
float TitleBarHeight() const
bool Overlaps(const ImRect &r) const
ImVector< ImGuiID > IDStack
ImGuiMouseCursor MouseCursor
int ImGuiColumnsFlags
Definition: imgui.h:133
float KeyRepeatRate
Definition: imgui.h:1287
ImGuiNextWindowData NextWindowData
ImVec2 pos
Definition: imgui.h:1741
ImVec2 TouchExtraPadding
Definition: imgui.h:1241
IMGUI_API void RenderTextClipped(const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, const ImVec2 *text_size_if_known, const ImVec2 &align=ImVec2(0, 0), const ImRect *clip_rect=NULL)
Definition: imgui.cpp:2296
ImRect Rect() const
static ImVec2 CalcSizeAfterConstraint(ImGuiWindow *window, ImVec2 new_size)
Definition: imgui.cpp:4442
ImGuiWindow * GetCurrentWindow()
IMGUI_API void SetAllInt(int val)
Definition: imgui.cpp:1959
IMGUI_API ImVec2 GetWindowPos()
Definition: imgui.cpp:5894
void Floor()
ImGuiStorage * StateStorage
void(* ReadLineFn)(ImGuiContext *ctx, ImGuiSettingsHandler *handler, void *entry, const char *line)
IMGUI_API ImGuiStyle & GetStyle()
Definition: imgui.cpp:2981
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v)
Definition: imgui.cpp:1735
int ImGuiCol
Definition: imgui.h:120
ImVector< ImGuiWindow * > ChildWindows
ImRect OuterRectClipped
static const ImGuiStyleVarInfo * GetStyleVarInfo(ImGuiStyleVar idx)
Definition: imgui.cpp:5690
int ImGuiNavInput
Definition: imgui.h:125
IMGUI_API void SetItemAllowOverlap()
Definition: imgui.cpp:4202
IMGUI_API void CloseCurrentPopup()
Definition: imgui.cpp:6736
IMGUI_API void PushClipRectFullScreen()
Definition: imgui_draw.cpp:495
static void *(* GImAllocatorAllocFunc)(size_t size, void *user_data)
Definition: imgui.cpp:1056
IMGUI_API void PopClipRect()
Definition: imgui.cpp:3682
const char * IniFilename
Definition: imgui.h:1280
ImGuiColumnsSet * ColumnsSet
float MouseDownDurationPrev[5]
Definition: imgui.h:1388
void ImStrTrimBlanks(char *buf)
Definition: imgui.cpp:1357
IMGUI_API void OpenPopup(const char *str_id)
Definition: imgui.cpp:6610
ImGuiCond SizeConstraintCond
IMGUI_API const char * SaveIniSettingsToMemory(size_t *out_ini_size=NULL)
Definition: imgui.cpp:8917
static bool NavScoreItem(ImGuiNavMoveResult *result, ImRect cand)
Definition: imgui.cpp:7010
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y)
Definition: imgui.cpp:2861
float WindowBorderSize
Definition: imgui.h:1229
void Translate(const ImVec2 &d)
IMGUI_API ImGuiSettingsHandler * FindSettingsHandler(const char *type_name)
Definition: imgui.cpp:8828
IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
FILE * ImFileOpen(const char *filename, const char *mode)
Definition: imgui.cpp:1467
static ImDrawList * GetOverlayDrawList(ImGuiWindow *)
Definition: imgui.cpp:3004
ImGuiNavLayer NavLayerCurrent
static bool BeginChildEx(const char *name, ImGuiID id, const ImVec2 &size_arg, bool border, ImGuiWindowFlags flags)
Definition: imgui.cpp:4237
static const char * GetClipboardTextFn_DefaultImpl(void *user_data)
Definition: imgui.cpp:9060
ImGuiWindow * Window
int ImGuiNavHighlightFlags
ImVec2 BackupCursorMaxPos
ImVec2 SizeContents
ImGuiStorage WindowsById
float Scale
Definition: imgui.h:2075
bool IsKeyPressedMap(ImGuiKey key, bool repeat=true)
ImVector< ImDrawIdx > IdxBuffer
Definition: imgui.h:1791
void reserve(int new_capacity)
Definition: imgui.h:1203
void Clear()
Definition: imgui.h:1465
static ImVec2 NavCalcPreferredRefPos()
Definition: imgui.cpp:7329
IMGUI_API ImDrawData * GetDrawData()
Definition: imgui.cpp:2988
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow *window, ImGuiWindowFlags flags, ImGuiWindow *parent_window)
Definition: imgui.cpp:4717
ImVector< char > TempBuffer
IMGUI_API void ClearActiveID()
Definition: imgui.cpp:2617
IMGUI_API const ImVec4 & GetStyleColorVec4(ImGuiCol idx)
Definition: imgui.cpp:1800
static ImRect GetResizeBorderRect(ImGuiWindow *window, int border_n, float perp_padding, float thickness)
Definition: imgui.cpp:4595
IMGUI_API void Columns(int count=1, const char *id=NULL, bool border=true)
Definition: imgui.cpp:8296
bool AntiAliasedFill
Definition: imgui.h:1255
IMGUI_API void SetWindowFontScale(float scale)
Definition: imgui.cpp:6184
ImVec2 Min
const char * ImStreolRange(const char *str, const char *str_end)
Definition: imgui.cpp:1321
error
Error code indicating why parse failed.
Definition: sajson.h:643
IMGUI_API float GetFrameHeightWithSpacing()
Definition: imgui.cpp:6157
bool DragDropWithinSourceOrTarget
IMGUI_API bool IsMouseDoubleClicked(int button)
Definition: imgui.cpp:4051
static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
Definition: imgui.cpp:6986
bool Contains(const ImVec2 &p) const
ImFontAtlas * Fonts
Definition: imgui.h:1290
ImFont * FontDefault
Definition: imgui.h:1293
T * begin()
Definition: imgui.h:1190
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect &bb_rel, ImGuiNavMoveFlags move_flags)
Definition: imgui.cpp:7223
ImGuiID NavInputId
ImGuiWindow * HoveredWindow
ImGuiID DragDropAcceptIdCurr
IMGUI_API bool IsAnyItemActive()
Definition: imgui.cpp:4177
ImVec2 WindowPadding
Definition: imgui.h:1227
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b)
Definition: imgui.cpp:1757
IMGUI_API void PopID()
Definition: imgui.cpp:6372
float WindowRounding
Definition: imgui.h:1228
bool NavDisableMouseHover
IMGUI_API bool SetDragDropPayload(const char *type, const void *data, size_t size, ImGuiCond cond=0)
Definition: imgui.cpp:8447
IMGUI_API ImDrawListSharedData * GetDrawListSharedData()
Definition: imgui.cpp:3015
ImVector< unsigned char > DragDropPayloadBufHeap
IMGUI_API void ChannelsSplit(int channels_count)
Definition: imgui_draw.cpp:520
IMGUI_API float GetCursorPosY()
Definition: imgui.cpp:6206
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
Definition: imgui.cpp:6753
static float GetColumnsRectHalfWidth()
Definition: imgui.cpp:8051
ImVec2 PlatformImeLastPos
IMGUI_API void SetKeyboardFocusHere(int offset=0)
Definition: imgui.cpp:6310
void Add(const ImVec2 &p)
IMGUI_API bool IsClippedEx(const ImRect &bb, ImGuiID id, bool clip_even_when_logged)
Definition: imgui.cpp:2819
float ScrollbarSize
Definition: imgui.h:1244
IMGUI_API void LogFinish()
Definition: imgui.cpp:8732
ImGuiStyleVar VarIdx
ImGuiWindow * GetCurrentWindowRead()
IMGUI_API void SetScrollX(float scroll_x)
Definition: imgui.cpp:6272
bool IsNavInputDown(ImGuiNavInput n)
IMGUI_API void PopFont()
Definition: imgui.cpp:5563
ImVec2 ScrollTarget
float y
Definition: imgui.h:178
IMGUI_API void Render()
Definition: imgui.cpp:3780
IMGUI_API bool GetBool(ImGuiID key, bool default_val=false) const
Definition: imgui.cpp:1869
float x
Definition: imgui.h:166
bool ActiveIdPreviousFrameHasBeenEdited
ImGuiCond SetWindowSizeAllowFlags
IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in)
Definition: imgui.cpp:1713
float MenuBarHeight() const
IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul=1.0f)
Definition: imgui.cpp:1784
static void NavUpdateWindowing()
Definition: imgui.cpp:7817
float PopupRounding
Definition: imgui.h:1234
IMGUI_API void PopStyleColor(int count=1)
Definition: imgui.cpp:5644
ImVector< ImWchar > TextW
GLenum type
Definition: gl.h:1033
static void SetWindowPos(ImGuiWindow *window, const ImVec2 &pos, ImGuiCond cond)
Definition: imgui.cpp:5915
static T ImMin(T lhs, T rhs)
ImGuiID NavNextActivateId
ImGuiInputSource ActiveIdSource
ImVector< ImVec4 > _ClipRectStack
Definition: imgui.h:1801
ImGuiID NavJustMovedToId
IMGUI_API bool IsAnyMouseDown()
Definition: imgui.cpp:4017
IMGUI_API bool IsPopupOpen(const char *str_id)
Definition: imgui.cpp:6594
#define IM_NEW(_TYPE)
Definition: imgui.h:1524
IMGUI_API void SetWindowSize(const ImVec2 &size, ImGuiCond cond=0)
Definition: imgui.cpp:5982
float NavWindowingHighlightAlpha
ImGuiPopupPositionPolicy


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:21