xref: /aosp_15_r20/external/mesa3d/src/imgui/imgui.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker // dear imgui, v1.68 WIP
2*61046927SAndroid Build Coastguard Worker // (main code and documentation)
3*61046927SAndroid Build Coastguard Worker 
4*61046927SAndroid Build Coastguard Worker // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
5*61046927SAndroid Build Coastguard Worker // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
6*61046927SAndroid Build Coastguard Worker // Get latest version at https://github.com/ocornut/imgui
7*61046927SAndroid Build Coastguard Worker // Releases change-log at https://github.com/ocornut/imgui/releases
8*61046927SAndroid Build Coastguard Worker // Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started
9*61046927SAndroid Build Coastguard Worker // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker // Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
12*61046927SAndroid Build Coastguard Worker // See LICENSE.txt for copyright and licensing details (standard MIT License).
13*61046927SAndroid Build Coastguard Worker // This library is free but I need your support to sustain development and maintenance.
14*61046927SAndroid Build Coastguard Worker // Businesses: you can support continued maintenance and development via support contracts or sponsoring, see docs/README.
15*61046927SAndroid Build Coastguard Worker // Individuals: you can support continued maintenance and development via donations or Patreon https://www.patreon.com/imgui.
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
18*61046927SAndroid Build Coastguard Worker // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
19*61046927SAndroid Build Coastguard Worker // modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
20*61046927SAndroid Build Coastguard Worker // come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
21*61046927SAndroid Build Coastguard Worker // to a better solution or official support for them.
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker /*
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker Index of this file:
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker DOCUMENTATION
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker - MISSION STATEMENT
30*61046927SAndroid Build Coastguard Worker - END-USER GUIDE
31*61046927SAndroid Build Coastguard Worker - PROGRAMMER GUIDE (read me!)
32*61046927SAndroid Build Coastguard Worker   - Read first.
33*61046927SAndroid Build Coastguard Worker   - How to update to a newer version of Dear ImGui.
34*61046927SAndroid Build Coastguard Worker   - Getting started with integrating Dear ImGui in your code/engine.
35*61046927SAndroid Build Coastguard Worker   - This is how a simple application may look like (2 variations).
36*61046927SAndroid Build Coastguard Worker   - This is how a simple rendering function may look like.
37*61046927SAndroid Build Coastguard Worker   - Using gamepad/keyboard navigation controls.
38*61046927SAndroid Build Coastguard Worker - API BREAKING CHANGES (read me when you update!)
39*61046927SAndroid Build Coastguard Worker - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
40*61046927SAndroid Build Coastguard Worker   - How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
41*61046927SAndroid Build Coastguard Worker   - How can I display an image? What is ImTextureID, how does it works?
42*61046927SAndroid Build Coastguard Worker   - How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.
43*61046927SAndroid Build Coastguard Worker   - How can I use my own math types instead of ImVec2/ImVec4?
44*61046927SAndroid Build Coastguard Worker   - How can I load a different font than the default?
45*61046927SAndroid Build Coastguard Worker   - How can I easily use icons in my application?
46*61046927SAndroid Build Coastguard Worker   - How can I load multiple fonts?
47*61046927SAndroid Build Coastguard Worker   - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
48*61046927SAndroid Build Coastguard Worker   - How can I interact with standard C++ types (such as std::string and std::vector)?
49*61046927SAndroid Build Coastguard Worker   - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
50*61046927SAndroid Build Coastguard Worker   - How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad)
51*61046927SAndroid Build Coastguard Worker   - I integrated Dear ImGui in my engine and the text or lines are blurry..
52*61046927SAndroid Build Coastguard Worker   - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
53*61046927SAndroid Build Coastguard Worker   - How can I help?
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker CODE
56*61046927SAndroid Build Coastguard Worker (search for "[SECTION]" in the code to find them)
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker // [SECTION] FORWARD DECLARATIONS
59*61046927SAndroid Build Coastguard Worker // [SECTION] CONTEXT AND MEMORY ALLOCATORS
60*61046927SAndroid Build Coastguard Worker // [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
61*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
62*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPER/UTILITIES (ImText* functions)
63*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPER/UTILITIES (Color functions)
64*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiStorage
65*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiTextFilter
66*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiTextBuffer
67*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiListClipper
68*61046927SAndroid Build Coastguard Worker // [SECTION] RENDER HELPERS
69*61046927SAndroid Build Coastguard Worker // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
70*61046927SAndroid Build Coastguard Worker // [SECTION] TOOLTIPS
71*61046927SAndroid Build Coastguard Worker // [SECTION] POPUPS
72*61046927SAndroid Build Coastguard Worker // [SECTION] KEYBOARD/GAMEPAD NAVIGATION
73*61046927SAndroid Build Coastguard Worker // [SECTION] COLUMNS
74*61046927SAndroid Build Coastguard Worker // [SECTION] DRAG AND DROP
75*61046927SAndroid Build Coastguard Worker // [SECTION] LOGGING/CAPTURING
76*61046927SAndroid Build Coastguard Worker // [SECTION] SETTINGS
77*61046927SAndroid Build Coastguard Worker // [SECTION] PLATFORM DEPENDENT HELPERS
78*61046927SAndroid Build Coastguard Worker // [SECTION] METRICS/DEBUG WINDOW
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker */
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
83*61046927SAndroid Build Coastguard Worker // DOCUMENTATION
84*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker /*
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker  MISSION STATEMENT
89*61046927SAndroid Build Coastguard Worker  =================
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker  - Easy to use to create code-driven and data-driven tools.
92*61046927SAndroid Build Coastguard Worker  - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
93*61046927SAndroid Build Coastguard Worker  - Easy to hack and improve.
94*61046927SAndroid Build Coastguard Worker  - Minimize screen real-estate usage.
95*61046927SAndroid Build Coastguard Worker  - Minimize setup and maintenance.
96*61046927SAndroid Build Coastguard Worker  - Minimize state storage on user side.
97*61046927SAndroid Build Coastguard Worker  - Portable, minimize dependencies, run on target (consoles, phones, etc.).
98*61046927SAndroid Build Coastguard Worker  - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,.
99*61046927SAndroid Build Coastguard Worker    opening a tree node for the first time, etc. but a typical frame should not allocate anything).
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker  Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
102*61046927SAndroid Build Coastguard Worker  - Doesn't look fancy, doesn't animate.
103*61046927SAndroid Build Coastguard Worker  - Limited layout features, intricate layouts are typically crafted in code.
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker  END-USER GUIDE
107*61046927SAndroid Build Coastguard Worker  ==============
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker  - Double-click on title bar to collapse window.
110*61046927SAndroid Build Coastguard Worker  - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
111*61046927SAndroid Build Coastguard Worker  - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
112*61046927SAndroid Build Coastguard Worker  - Click and drag on any empty space to move window.
113*61046927SAndroid Build Coastguard Worker  - TAB/SHIFT+TAB to cycle through keyboard editable fields.
114*61046927SAndroid Build Coastguard Worker  - CTRL+Click on a slider or drag box to input value as text.
115*61046927SAndroid Build Coastguard Worker  - Use mouse wheel to scroll.
116*61046927SAndroid Build Coastguard Worker  - Text editor:
117*61046927SAndroid Build Coastguard Worker    - Hold SHIFT or use mouse to select text.
118*61046927SAndroid Build Coastguard Worker    - CTRL+Left/Right to word jump.
119*61046927SAndroid Build Coastguard Worker    - CTRL+Shift+Left/Right to select words.
120*61046927SAndroid Build Coastguard Worker    - CTRL+A our Double-Click to select all.
121*61046927SAndroid Build Coastguard Worker    - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
122*61046927SAndroid Build Coastguard Worker    - CTRL+Z,CTRL+Y to undo/redo.
123*61046927SAndroid Build Coastguard Worker    - ESCAPE to revert text to its original value.
124*61046927SAndroid Build Coastguard Worker    - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
125*61046927SAndroid Build Coastguard Worker    - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
126*61046927SAndroid Build Coastguard Worker  - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
127*61046927SAndroid Build Coastguard Worker  - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker  PROGRAMMER GUIDE
131*61046927SAndroid Build Coastguard Worker  ================
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker  READ FIRST:
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker  - Read the FAQ below this section!
136*61046927SAndroid Build Coastguard Worker  - 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*61046927SAndroid Build Coastguard Worker    or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs.
138*61046927SAndroid Build Coastguard Worker  - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
139*61046927SAndroid Build Coastguard Worker  - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
140*61046927SAndroid Build Coastguard Worker  - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
141*61046927SAndroid Build Coastguard Worker    You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links docs/README.md.
142*61046927SAndroid Build Coastguard Worker  - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances.
143*61046927SAndroid Build Coastguard Worker    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*61046927SAndroid Build Coastguard Worker    where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches.
145*61046927SAndroid Build Coastguard Worker  - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right.
146*61046927SAndroid Build Coastguard Worker  - This codebase is also optimized to yield decent performances with typical "Debug" builds settings.
147*61046927SAndroid Build Coastguard Worker  - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected).
148*61046927SAndroid Build Coastguard Worker    If you get an assert, read the messages and comments around the assert.
149*61046927SAndroid Build Coastguard Worker  - 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*61046927SAndroid Build Coastguard Worker  - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
151*61046927SAndroid Build Coastguard Worker    See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
152*61046927SAndroid Build Coastguard Worker    However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase.
153*61046927SAndroid Build Coastguard Worker  - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!).
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker  HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI:
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker  - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
158*61046927SAndroid Build Coastguard Worker  - Or maintain your own branch where you have imconfig.h modified.
159*61046927SAndroid Build Coastguard Worker  - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
160*61046927SAndroid Build Coastguard Worker    If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
161*61046927SAndroid Build Coastguard Worker    from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
162*61046927SAndroid Build Coastguard Worker    likely be a comment about it. Please report any issue to the GitHub page!
163*61046927SAndroid Build Coastguard Worker  - Try to keep your copy of dear imgui reasonably up to date.
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker  GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE:
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker  - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
168*61046927SAndroid Build Coastguard Worker  - Add the Dear ImGui source files to your projects or using your preferred build system.
169*61046927SAndroid Build Coastguard Worker    It is recommended you build and statically link the .cpp files as part of your project and not as shared library (DLL).
170*61046927SAndroid Build Coastguard Worker  - 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*61046927SAndroid Build Coastguard Worker  - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
172*61046927SAndroid Build Coastguard Worker  - 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*61046927SAndroid Build Coastguard Worker    Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
174*61046927SAndroid Build Coastguard Worker    phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render().
175*61046927SAndroid Build Coastguard Worker  - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
176*61046927SAndroid Build Coastguard Worker  - 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*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker  HOW A SIMPLE APPLICATION MAY LOOK LIKE:
179*61046927SAndroid Build Coastguard Worker  EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder).
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker      // Application init: create a dear imgui context, setup some options, load fonts
182*61046927SAndroid Build Coastguard Worker      ImGui::CreateContext();
183*61046927SAndroid Build Coastguard Worker      ImGuiIO& io = ImGui::GetIO();
184*61046927SAndroid Build Coastguard Worker      // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
185*61046927SAndroid Build Coastguard Worker      // TODO: Fill optional fields of the io structure later.
186*61046927SAndroid Build Coastguard Worker      // TODO: Load TTF/OTF fonts if you don't want to use the default font.
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker      // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11)
189*61046927SAndroid Build Coastguard Worker      ImGui_ImplWin32_Init(hwnd);
190*61046927SAndroid Build Coastguard Worker      ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker      // Application main loop
193*61046927SAndroid Build Coastguard Worker      while (true)
194*61046927SAndroid Build Coastguard Worker      {
195*61046927SAndroid Build Coastguard Worker          // Feed inputs to dear imgui, start new frame
196*61046927SAndroid Build Coastguard Worker          ImGui_ImplDX11_NewFrame();
197*61046927SAndroid Build Coastguard Worker          ImGui_ImplWin32_NewFrame();
198*61046927SAndroid Build Coastguard Worker          ImGui::NewFrame();
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker          // Any application code here
201*61046927SAndroid Build Coastguard Worker          ImGui::Text("Hello, world!");
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker          // Render dear imgui into screen
204*61046927SAndroid Build Coastguard Worker          ImGui::Render();
205*61046927SAndroid Build Coastguard Worker          ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
206*61046927SAndroid Build Coastguard Worker          g_pSwapChain->Present(1, 0);
207*61046927SAndroid Build Coastguard Worker      }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker      // Shutdown
210*61046927SAndroid Build Coastguard Worker      ImGui_ImplDX11_Shutdown();
211*61046927SAndroid Build Coastguard Worker      ImGui_ImplWin32_Shutdown();
212*61046927SAndroid Build Coastguard Worker      ImGui::DestroyContext();
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker  HOW A SIMPLE APPLICATION MAY LOOK LIKE:
215*61046927SAndroid Build Coastguard Worker  EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE.
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker      // Application init: create a dear imgui context, setup some options, load fonts
218*61046927SAndroid Build Coastguard Worker      ImGui::CreateContext();
219*61046927SAndroid Build Coastguard Worker      ImGuiIO& io = ImGui::GetIO();
220*61046927SAndroid Build Coastguard Worker      // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
221*61046927SAndroid Build Coastguard Worker      // TODO: Fill optional fields of the io structure later.
222*61046927SAndroid Build Coastguard Worker      // TODO: Load TTF/OTF fonts if you don't want to use the default font.
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker      // Build and load the texture atlas into a texture
225*61046927SAndroid Build Coastguard Worker      // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
226*61046927SAndroid Build Coastguard Worker      int width, height;
227*61046927SAndroid Build Coastguard Worker      unsigned char* pixels = NULL;
228*61046927SAndroid Build Coastguard Worker      io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker      // At this point you've got the texture data and you need to upload that your your graphic system:
231*61046927SAndroid Build Coastguard Worker      // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
232*61046927SAndroid Build Coastguard Worker      // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID.
233*61046927SAndroid Build Coastguard Worker      MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
234*61046927SAndroid Build Coastguard Worker      io.Fonts->TexID = (void*)texture;
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker      // Application main loop
237*61046927SAndroid Build Coastguard Worker      while (true)
238*61046927SAndroid Build Coastguard Worker      {
239*61046927SAndroid Build Coastguard Worker         // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
240*61046927SAndroid Build Coastguard Worker         // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings)
241*61046927SAndroid Build Coastguard Worker         io.DeltaTime = 1.0f/60.0f;              // set the time elapsed since the previous frame (in seconds)
242*61046927SAndroid Build Coastguard Worker         io.DisplaySize.x = 1920.0f;             // set the current display width
243*61046927SAndroid Build Coastguard Worker         io.DisplaySize.y = 1280.0f;             // set the current display height here
244*61046927SAndroid Build Coastguard Worker         io.MousePos = my_mouse_pos;             // set the mouse position
245*61046927SAndroid Build Coastguard Worker         io.MouseDown[0] = my_mouse_buttons[0];  // set the mouse button states
246*61046927SAndroid Build Coastguard Worker         io.MouseDown[1] = my_mouse_buttons[1];
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker         // Call NewFrame(), after this point you can use ImGui::* functions anytime
249*61046927SAndroid Build Coastguard Worker         // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use imgui everywhere)
250*61046927SAndroid Build Coastguard Worker         ImGui::NewFrame();
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker         // Most of your application code here
253*61046927SAndroid Build Coastguard Worker         ImGui::Text("Hello, world!");
254*61046927SAndroid Build Coastguard Worker         MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
255*61046927SAndroid Build Coastguard Worker         MyGameRender(); // may use any ImGui functions as well!
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker         // Render imgui, swap buffers
258*61046927SAndroid Build Coastguard Worker         // (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*61046927SAndroid Build Coastguard Worker         ImGui::EndFrame();
260*61046927SAndroid Build Coastguard Worker         ImGui::Render();
261*61046927SAndroid Build Coastguard Worker         ImDrawData* draw_data = ImGui::GetDrawData();
262*61046927SAndroid Build Coastguard Worker         MyImGuiRenderFunction(draw_data);
263*61046927SAndroid Build Coastguard Worker         SwapBuffers();
264*61046927SAndroid Build Coastguard Worker      }
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker      // Shutdown
267*61046927SAndroid Build Coastguard Worker      ImGui::DestroyContext();
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker  HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE:
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker     void void MyImGuiRenderFunction(ImDrawData* draw_data)
272*61046927SAndroid Build Coastguard Worker     {
273*61046927SAndroid Build Coastguard Worker        // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
274*61046927SAndroid Build Coastguard Worker        // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
275*61046927SAndroid Build Coastguard Worker        // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
276*61046927SAndroid Build Coastguard Worker        // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
277*61046927SAndroid Build Coastguard Worker        for (int n = 0; n < draw_data->CmdListsCount; n++)
278*61046927SAndroid Build Coastguard Worker        {
279*61046927SAndroid Build Coastguard Worker           const ImDrawList* cmd_list = draw_data->CmdLists[n];
280*61046927SAndroid Build Coastguard Worker           const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;  // vertex buffer generated by ImGui
281*61046927SAndroid Build Coastguard Worker           const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;   // index buffer generated by ImGui
282*61046927SAndroid Build Coastguard Worker           for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
283*61046927SAndroid Build Coastguard Worker           {
284*61046927SAndroid Build Coastguard Worker              const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
285*61046927SAndroid Build Coastguard Worker              if (pcmd->UserCallback)
286*61046927SAndroid Build Coastguard Worker              {
287*61046927SAndroid Build Coastguard Worker                  pcmd->UserCallback(cmd_list, pcmd);
288*61046927SAndroid Build Coastguard Worker              }
289*61046927SAndroid Build Coastguard Worker              else
290*61046927SAndroid Build Coastguard Worker              {
291*61046927SAndroid Build Coastguard Worker                  // The texture for the draw call is specified by pcmd->TextureId.
292*61046927SAndroid Build Coastguard Worker                  // The vast majority of draw calls will use the imgui texture atlas, which value you have set yourself during initialization.
293*61046927SAndroid Build Coastguard Worker                  MyEngineBindTexture((MyTexture*)pcmd->TextureId);
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker                  // We are using scissoring to clip some objects. All low-level graphics API should supports it.
296*61046927SAndroid Build Coastguard Worker                  // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
297*61046927SAndroid Build Coastguard Worker                  //   (some elements visible outside their bounds) but you can fix that once everything else works!
298*61046927SAndroid Build Coastguard Worker                  // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize)
299*61046927SAndroid Build Coastguard Worker                  //   In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize.
300*61046927SAndroid Build Coastguard Worker                  //   However, in the interest of supporting multi-viewport applications in the future (see 'viewport' branch on github),
301*61046927SAndroid Build Coastguard Worker                  //   always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
302*61046927SAndroid Build Coastguard Worker                  // - 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*61046927SAndroid Build Coastguard Worker                  ImVec2 pos = draw_data->DisplayPos;
304*61046927SAndroid Build Coastguard Worker                  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*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker                  // Render 'pcmd->ElemCount/3' indexed triangles.
307*61046927SAndroid Build Coastguard Worker                  // 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*61046927SAndroid Build Coastguard Worker                  MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
309*61046927SAndroid Build Coastguard Worker              }
310*61046927SAndroid Build Coastguard Worker              idx_buffer += pcmd->ElemCount;
311*61046927SAndroid Build Coastguard Worker           }
312*61046927SAndroid Build Coastguard Worker        }
313*61046927SAndroid Build Coastguard Worker     }
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker  - The examples/ folders contains many actual implementation of the pseudo-codes above.
316*61046927SAndroid Build Coastguard Worker  - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated.
317*61046927SAndroid Build Coastguard Worker    They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs
318*61046927SAndroid Build Coastguard Worker    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*61046927SAndroid Build Coastguard Worker  - Please read the FAQ below!. Amusingly, it is called a FAQ because people frequently run into the same issues!
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker  USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker  - The gamepad/keyboard navigation is fairly functional and keeps being improved.
324*61046927SAndroid Build Coastguard Worker  - Gamepad support is particularly useful to use dear imgui on a console system (e.g. PS4, Switch, XB1) without a mouse!
325*61046927SAndroid Build Coastguard Worker  - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
326*61046927SAndroid Build Coastguard Worker  - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
327*61046927SAndroid Build Coastguard Worker  - Gamepad:
328*61046927SAndroid Build Coastguard Worker     - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
329*61046927SAndroid Build Coastguard Worker     - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
330*61046927SAndroid Build Coastguard Worker       Note that io.NavInputs[] is cleared by EndFrame().
331*61046927SAndroid Build Coastguard Worker     - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
332*61046927SAndroid Build Coastguard Worker          0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
333*61046927SAndroid Build Coastguard Worker     - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
334*61046927SAndroid Build Coastguard Worker       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*61046927SAndroid Build Coastguard Worker     - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://goo.gl/9LgVZW.
336*61046927SAndroid Build Coastguard Worker     - 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*61046927SAndroid Build Coastguard Worker       to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
338*61046927SAndroid Build Coastguard Worker  - Keyboard:
339*61046927SAndroid Build Coastguard Worker     - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
340*61046927SAndroid Build Coastguard Worker       NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
341*61046927SAndroid Build Coastguard Worker     - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
342*61046927SAndroid Build Coastguard Worker       will be set. For more advanced uses, you may want to read from:
343*61046927SAndroid Build Coastguard Worker        - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
344*61046927SAndroid Build Coastguard Worker        - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
345*61046927SAndroid Build Coastguard Worker        - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
346*61046927SAndroid Build Coastguard Worker       Please reach out if you think the game vs navigation input sharing could be improved.
347*61046927SAndroid Build Coastguard Worker  - Mouse:
348*61046927SAndroid Build Coastguard Worker     - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
349*61046927SAndroid Build Coastguard Worker     - 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*61046927SAndroid Build Coastguard Worker     - 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*61046927SAndroid Build Coastguard Worker       Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
352*61046927SAndroid Build Coastguard Worker       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*61046927SAndroid Build Coastguard Worker       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*61046927SAndroid Build Coastguard Worker       (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*61046927SAndroid Build Coastguard Worker       (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*61046927SAndroid Build Coastguard Worker        to set a boolean to ignore your other external mouse positions until the external source is moved again.)
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker  API BREAKING CHANGES
360*61046927SAndroid Build Coastguard Worker  ====================
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker  Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
363*61046927SAndroid Build Coastguard Worker  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*61046927SAndroid Build Coastguard Worker  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*61046927SAndroid Build Coastguard Worker  You can read releases logs https://github.com/ocornut/imgui/releases for more details.
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker  - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with a dummy small value!
368*61046927SAndroid Build Coastguard Worker  - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already).
369*61046927SAndroid Build Coastguard Worker  - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
370*61046927SAndroid Build Coastguard Worker  - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Keep redirection typedef (will obsolete).
371*61046927SAndroid Build Coastguard Worker  - 2018/12/20 (1.67) - made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable side-effects.
372*61046927SAndroid Build Coastguard Worker  - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags.
373*61046927SAndroid Build Coastguard Worker  - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files.
374*61046927SAndroid Build Coastguard Worker  - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
375*61046927SAndroid Build Coastguard Worker  - 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.
376*61046927SAndroid Build Coastguard Worker                        If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths.
377*61046927SAndroid Build Coastguard Worker  - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
378*61046927SAndroid Build Coastguard Worker  - 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.
379*61046927SAndroid Build Coastguard Worker                        NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED.
380*61046927SAndroid Build Coastguard Worker                        Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions.
381*61046927SAndroid Build Coastguard Worker  - 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).
382*61046927SAndroid Build Coastguard Worker  - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete).
383*61046927SAndroid Build Coastguard Worker  - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly).
384*61046927SAndroid Build Coastguard Worker  - 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.
385*61046927SAndroid Build Coastguard Worker  - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency.
386*61046927SAndroid Build Coastguard Worker  - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
387*61046927SAndroid Build Coastguard Worker  - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
388*61046927SAndroid Build Coastguard Worker  - 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.).
389*61046927SAndroid Build Coastguard Worker                        old binding will still work as is, however prefer using the separated bindings as they will be updated to be multi-viewport conformant.
390*61046927SAndroid Build Coastguard Worker                        when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call.
391*61046927SAndroid Build Coastguard Worker  - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
392*61046927SAndroid Build Coastguard Worker  - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
393*61046927SAndroid Build Coastguard Worker  - 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.
394*61046927SAndroid Build Coastguard Worker                        If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
395*61046927SAndroid Build Coastguard Worker                        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.
396*61046927SAndroid Build Coastguard Worker                        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.
397*61046927SAndroid Build Coastguard Worker  - 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",
398*61046927SAndroid Build Coastguard Worker                        consistent with other functions. Kept redirection functions (will obsolete).
399*61046927SAndroid Build Coastguard Worker  - 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.
400*61046927SAndroid Build Coastguard Worker  - 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).
401*61046927SAndroid Build Coastguard Worker  - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
402*61046927SAndroid Build Coastguard Worker  - 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.
403*61046927SAndroid Build Coastguard Worker  - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
404*61046927SAndroid Build Coastguard Worker  - 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.
405*61046927SAndroid Build Coastguard Worker  - 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.
406*61046927SAndroid Build Coastguard Worker  - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
407*61046927SAndroid Build Coastguard Worker                        - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
408*61046927SAndroid Build Coastguard Worker                        - removed Shutdown() function, as DestroyContext() serve this purpose.
409*61046927SAndroid Build Coastguard Worker                        - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
410*61046927SAndroid Build Coastguard Worker                        - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
411*61046927SAndroid Build Coastguard Worker                        - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
412*61046927SAndroid Build Coastguard Worker  - 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.
413*61046927SAndroid Build Coastguard Worker  - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
414*61046927SAndroid Build Coastguard Worker  - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
415*61046927SAndroid Build Coastguard Worker  - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
416*61046927SAndroid Build Coastguard Worker  - 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.
417*61046927SAndroid Build Coastguard Worker  - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
418*61046927SAndroid Build Coastguard Worker  - 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
419*61046927SAndroid Build Coastguard Worker  - 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.
420*61046927SAndroid Build Coastguard Worker  - 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.
421*61046927SAndroid Build Coastguard Worker  - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
422*61046927SAndroid Build Coastguard Worker  - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
423*61046927SAndroid Build Coastguard Worker                      - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
424*61046927SAndroid Build Coastguard Worker  - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
425*61046927SAndroid Build Coastguard Worker  - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
426*61046927SAndroid Build Coastguard Worker  - 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.
427*61046927SAndroid Build Coastguard Worker  - 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.
428*61046927SAndroid Build Coastguard Worker                        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.
429*61046927SAndroid Build Coastguard Worker  - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
430*61046927SAndroid Build Coastguard Worker  - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
431*61046927SAndroid Build Coastguard Worker  - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
432*61046927SAndroid Build Coastguard Worker  - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
433*61046927SAndroid Build Coastguard Worker  - 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.
434*61046927SAndroid Build Coastguard Worker  - 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.
435*61046927SAndroid Build Coastguard Worker  - 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.
436*61046927SAndroid Build Coastguard Worker                        removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
437*61046927SAndroid Build Coastguard Worker  - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
438*61046927SAndroid Build Coastguard Worker  - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
439*61046927SAndroid Build Coastguard Worker  - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Keep redirection typedef (will obsolete).
440*61046927SAndroid Build Coastguard Worker  - 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).
441*61046927SAndroid Build Coastguard Worker  - 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)".
442*61046927SAndroid Build Coastguard Worker  - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
443*61046927SAndroid Build Coastguard Worker                      - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
444*61046927SAndroid Build Coastguard Worker                      - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
445*61046927SAndroid Build Coastguard Worker  - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
446*61046927SAndroid Build Coastguard Worker  - 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.
447*61046927SAndroid Build Coastguard Worker  - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
448*61046927SAndroid Build Coastguard Worker  - 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.
449*61046927SAndroid Build Coastguard Worker  - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
450*61046927SAndroid Build Coastguard Worker  - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
451*61046927SAndroid Build Coastguard Worker  - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
452*61046927SAndroid Build Coastguard Worker  - 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.
453*61046927SAndroid Build Coastguard Worker                      - 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.
454*61046927SAndroid Build Coastguard Worker                      - 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))'
455*61046927SAndroid Build Coastguard Worker  - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
456*61046927SAndroid Build Coastguard Worker  - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
457*61046927SAndroid Build Coastguard Worker  - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
458*61046927SAndroid Build Coastguard Worker  - 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().
459*61046927SAndroid Build Coastguard Worker  - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
460*61046927SAndroid Build Coastguard Worker  - 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.
461*61046927SAndroid Build Coastguard Worker  - 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.
462*61046927SAndroid Build Coastguard Worker  - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
463*61046927SAndroid Build Coastguard Worker                        If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you.
464*61046927SAndroid Build Coastguard Worker                        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.
465*61046927SAndroid Build Coastguard Worker                        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.
466*61046927SAndroid Build Coastguard Worker                            ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
467*61046927SAndroid Build Coastguard Worker                            {
468*61046927SAndroid Build Coastguard Worker                                float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
469*61046927SAndroid Build Coastguard Worker                                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);
470*61046927SAndroid Build Coastguard Worker                            }
471*61046927SAndroid Build Coastguard Worker                        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.
472*61046927SAndroid Build Coastguard Worker  - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
473*61046927SAndroid Build Coastguard Worker  - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
474*61046927SAndroid Build Coastguard Worker  - 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).
475*61046927SAndroid Build Coastguard Worker  - 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.
476*61046927SAndroid Build Coastguard Worker  - 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).
477*61046927SAndroid Build Coastguard Worker  - 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)
478*61046927SAndroid Build Coastguard Worker  - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
479*61046927SAndroid Build Coastguard Worker  - 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.
480*61046927SAndroid Build Coastguard Worker  - 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.
481*61046927SAndroid Build Coastguard Worker  - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
482*61046927SAndroid Build Coastguard Worker  - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
483*61046927SAndroid Build Coastguard Worker  - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
484*61046927SAndroid Build Coastguard Worker                        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.
485*61046927SAndroid Build Coastguard Worker                        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!
486*61046927SAndroid Build Coastguard Worker  - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
487*61046927SAndroid Build Coastguard Worker  - 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.
488*61046927SAndroid Build Coastguard Worker  - 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
489*61046927SAndroid Build Coastguard Worker  - 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.
490*61046927SAndroid Build Coastguard Worker                        you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
491*61046927SAndroid Build Coastguard Worker  - 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.
492*61046927SAndroid Build Coastguard Worker                        this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
493*61046927SAndroid Build Coastguard Worker                      - 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.
494*61046927SAndroid Build Coastguard Worker                      - the signature of the io.RenderDrawListsFn handler has changed!
495*61046927SAndroid Build Coastguard Worker                        old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
496*61046927SAndroid Build Coastguard Worker                        new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
497*61046927SAndroid Build Coastguard Worker                          parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
498*61046927SAndroid Build Coastguard Worker                          ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
499*61046927SAndroid Build Coastguard Worker                          ImDrawCmd:  'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
500*61046927SAndroid Build Coastguard Worker                      - 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.
501*61046927SAndroid Build Coastguard Worker                      - 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!
502*61046927SAndroid Build Coastguard Worker                      - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
503*61046927SAndroid Build Coastguard Worker  - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
504*61046927SAndroid Build Coastguard Worker  - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
505*61046927SAndroid Build Coastguard Worker  - 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.
506*61046927SAndroid Build Coastguard Worker  - 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
507*61046927SAndroid Build Coastguard Worker  - 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!
508*61046927SAndroid Build Coastguard Worker  - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
509*61046927SAndroid Build Coastguard Worker  - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
510*61046927SAndroid Build Coastguard Worker  - 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.
511*61046927SAndroid Build Coastguard Worker  - 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.
512*61046927SAndroid Build Coastguard Worker  - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
513*61046927SAndroid Build Coastguard Worker  - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
514*61046927SAndroid Build Coastguard Worker  - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
515*61046927SAndroid Build Coastguard Worker  - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
516*61046927SAndroid Build Coastguard Worker  - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
517*61046927SAndroid Build Coastguard Worker  - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
518*61046927SAndroid Build Coastguard Worker  - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
519*61046927SAndroid Build Coastguard Worker  - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
520*61046927SAndroid Build Coastguard Worker  - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
521*61046927SAndroid Build Coastguard Worker  - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
522*61046927SAndroid Build Coastguard Worker  - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
523*61046927SAndroid Build Coastguard Worker  - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
524*61046927SAndroid Build Coastguard Worker  - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
525*61046927SAndroid Build Coastguard Worker  - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
526*61046927SAndroid Build Coastguard Worker  - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
527*61046927SAndroid Build Coastguard Worker  - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
528*61046927SAndroid Build Coastguard Worker  - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
529*61046927SAndroid Build Coastguard Worker               (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
530*61046927SAndroid Build Coastguard Worker                        font init:  { const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>; }
531*61046927SAndroid Build Coastguard Worker                        became:     { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; }
532*61046927SAndroid Build Coastguard Worker                        you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
533*61046927SAndroid Build Coastguard Worker                        it is now recommended that you sample the font texture with bilinear interpolation.
534*61046927SAndroid Build Coastguard Worker               (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
535*61046927SAndroid Build Coastguard Worker               (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
536*61046927SAndroid Build Coastguard Worker               (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
537*61046927SAndroid Build Coastguard Worker  - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
538*61046927SAndroid Build Coastguard Worker  - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
539*61046927SAndroid Build Coastguard Worker  - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
540*61046927SAndroid Build Coastguard Worker  - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
541*61046927SAndroid Build Coastguard Worker  - 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)
542*61046927SAndroid Build Coastguard Worker  - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
543*61046927SAndroid Build Coastguard Worker  - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
544*61046927SAndroid Build Coastguard Worker  - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
545*61046927SAndroid Build Coastguard Worker  - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
546*61046927SAndroid Build Coastguard Worker  - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
547*61046927SAndroid Build Coastguard Worker  - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker  FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
551*61046927SAndroid Build Coastguard Worker  ======================================
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker  Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
554*61046927SAndroid Build Coastguard Worker  A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } )
555*61046927SAndroid Build Coastguard Worker     - 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.
556*61046927SAndroid Build Coastguard Worker     - 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.
557*61046927SAndroid Build Coastguard Worker     - 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).
558*61046927SAndroid Build Coastguard Worker     Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false.
559*61046927SAndroid Build Coastguard Worker      This is because imgui needs to detect that you clicked in the void to unfocus its own windows.
560*61046927SAndroid Build Coastguard Worker     Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!).
561*61046927SAndroid Build Coastguard Worker      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.
562*61046927SAndroid Build Coastguard Worker      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
563*61046927SAndroid Build Coastguard Worker      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().
564*61046927SAndroid Build Coastguard Worker     Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically
565*61046927SAndroid Build Coastguard Worker      have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
566*61046927SAndroid Build Coastguard Worker      were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker  Q: How can I display an image? What is ImTextureID, how does it works?
569*61046927SAndroid Build Coastguard Worker  A: Short explanation:
570*61046927SAndroid Build Coastguard Worker     - 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.
571*61046927SAndroid Build Coastguard Worker     - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
572*61046927SAndroid Build Coastguard Worker     - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
573*61046927SAndroid Build Coastguard Worker       Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker     Long explanation:
576*61046927SAndroid Build Coastguard Worker     - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices.
577*61046927SAndroid Build Coastguard Worker       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
578*61046927SAndroid Build Coastguard Worker       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.).
579*61046927SAndroid Build Coastguard Worker     - 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.
580*61046927SAndroid Build Coastguard Worker       We carry the information to identify a "texture" in the ImTextureID type.
581*61046927SAndroid Build Coastguard Worker       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.
582*61046927SAndroid Build Coastguard Worker       Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
583*61046927SAndroid Build Coastguard Worker     - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying
584*61046927SAndroid Build Coastguard Worker       an image from the end-user perspective. This is what the _examples_ rendering functions are using:
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker          OpenGL:     ImTextureID = GLuint                       (see ImGui_ImplGlfwGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp)
587*61046927SAndroid Build Coastguard Worker          DirectX9:   ImTextureID = LPDIRECT3DTEXTURE9           (see ImGui_ImplDX9_RenderDrawData()     function in imgui_impl_dx9.cpp)
588*61046927SAndroid Build Coastguard Worker          DirectX11:  ImTextureID = ID3D11ShaderResourceView*    (see ImGui_ImplDX11_RenderDrawData()    function in imgui_impl_dx11.cpp)
589*61046927SAndroid Build Coastguard Worker          DirectX12:  ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE  (see ImGui_ImplDX12_RenderDrawData()    function in imgui_impl_dx12.cpp)
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker       For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
592*61046927SAndroid Build Coastguard Worker       Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure
593*61046927SAndroid Build Coastguard Worker       tying together both the texture and information about its format and how to read it.
594*61046927SAndroid Build Coastguard Worker     - 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
595*61046927SAndroid Build Coastguard Worker       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
596*61046927SAndroid Build Coastguard Worker       is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
597*61046927SAndroid Build Coastguard Worker       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
598*61046927SAndroid Build Coastguard Worker       representation suggested by the example bindings is probably the best choice.
599*61046927SAndroid Build Coastguard Worker       (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker     User code may do:
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker         // Cast our texture type to ImTextureID / void*
604*61046927SAndroid Build Coastguard Worker         MyTexture* texture = g_CoffeeTableTexture;
605*61046927SAndroid Build Coastguard Worker         ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker     The renderer function called after ImGui::Render() will receive that same value that the user code passed:
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker         // Cast ImTextureID / void* stored in the draw command as our texture type
610*61046927SAndroid Build Coastguard Worker         MyTexture* texture = (MyTexture*)pcmd->TextureId;
611*61046927SAndroid Build Coastguard Worker         MyEngineBindTexture2D(texture);
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker     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.
614*61046927SAndroid Build Coastguard Worker     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.
615*61046927SAndroid Build Coastguard Worker     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.
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker     Here's a simplified OpenGL example using stb_image.h:
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker         // Use stb_image.h to load a PNG from disk and turn it into raw RGBA pixel data:
620*61046927SAndroid Build Coastguard Worker         #define STB_IMAGE_IMPLEMENTATION
621*61046927SAndroid Build Coastguard Worker         #include <stb_image.h>
622*61046927SAndroid Build Coastguard Worker         [...]
623*61046927SAndroid Build Coastguard Worker         int my_image_width, my_image_height;
624*61046927SAndroid Build Coastguard Worker         unsigned char* my_image_data = stbi_load("my_image.png", &my_image_width, &my_image_height, NULL, 4);
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker         // Turn the RGBA pixel data into an OpenGL texture:
627*61046927SAndroid Build Coastguard Worker         GLuint my_opengl_texture;
628*61046927SAndroid Build Coastguard Worker         glGenTextures(1, &my_opengl_texture);
629*61046927SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, my_opengl_texture);
630*61046927SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
631*61046927SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
632*61046927SAndroid Build Coastguard Worker         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
633*61046927SAndroid Build Coastguard Worker         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker         // 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:
636*61046927SAndroid Build Coastguard Worker         ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(my_image_width, my_image_height));
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker     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.
639*61046927SAndroid Build Coastguard Worker     Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTexture / void*.
640*61046927SAndroid Build Coastguard Worker     Examples:
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker         GLuint my_tex = XXX;
643*61046927SAndroid Build Coastguard Worker         void* my_void_ptr;
644*61046927SAndroid Build Coastguard Worker         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)
645*61046927SAndroid Build Coastguard Worker         my_tex = (GLuint)(intptr_t)my_void_ptr;                 // cast a void* into a GLuint
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker         ID3D11ShaderResourceView* my_dx11_srv = XXX;
648*61046927SAndroid Build Coastguard Worker         void* my_void_ptr;
649*61046927SAndroid Build Coastguard Worker         my_void_ptr = (void*)my_dx11_srv;                       // cast a ID3D11ShaderResourceView* into an opaque void*
650*61046927SAndroid Build Coastguard Worker         my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr;   // cast a void* into a ID3D11ShaderResourceView*
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker     Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker  Q: How can I have multiple widgets with the same label or with an empty label?
655*61046927SAndroid Build Coastguard Worker  Q: I have multiple widgets with the same label, and only the first one works. Why is that?
656*61046927SAndroid Build Coastguard Worker  A: A primer on labels and the ID Stack...
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker     Dear ImGui internally need to uniquely identify UI elements.
659*61046927SAndroid Build Coastguard Worker     Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
660*61046927SAndroid Build Coastguard Worker     Interactive widgets (such as calls to Button buttons) need a unique ID.
661*61046927SAndroid Build Coastguard Worker     Unique ID are used internally to track active widgets and occasionally associate state to widgets.
662*61046927SAndroid Build Coastguard Worker     Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker    - Unique ID are often derived from a string label:
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker        Button("OK");          // Label = "OK",     ID = hash of (..., "OK")
667*61046927SAndroid Build Coastguard Worker        Button("Cancel");      // Label = "Cancel", ID = hash of (..., "Cancel")
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker    - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
670*61046927SAndroid Build Coastguard Worker      two buttons labeled "OK" in different windows or different tree locations is fine.
671*61046927SAndroid Build Coastguard Worker      We used "..." above to signify whatever was already pushed to the ID stack previously:
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker        Begin("MyWindow");
674*61046927SAndroid Build Coastguard Worker        Button("OK");          // Label = "OK",     ID = hash of ("MyWindow", "OK")
675*61046927SAndroid Build Coastguard Worker        End();
676*61046927SAndroid Build Coastguard Worker        Begin("MyOtherWindow");
677*61046927SAndroid Build Coastguard Worker        Button("OK");          // Label = "OK",     ID = hash of ("MyOtherWindow", "OK")
678*61046927SAndroid Build Coastguard Worker        End();
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker    - If you have a same ID twice in the same location, you'll have a conflict:
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker        Button("OK");
683*61046927SAndroid Build Coastguard Worker        Button("OK");          // ID collision! Interacting with either button will trigger the first one.
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker      Fear not! this is easy to solve and there are many ways to solve it!
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker    - Solving ID conflict in a simple/local context:
688*61046927SAndroid Build Coastguard Worker      When passing a label you can optionally specify extra ID information within string itself.
689*61046927SAndroid Build Coastguard Worker      Use "##" to pass a complement to the ID that won't be visible to the end-user.
690*61046927SAndroid Build Coastguard Worker      This helps solving the simple collision cases when you know e.g. at compilation time which items
691*61046927SAndroid Build Coastguard Worker      are going to be created:
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker        Begin("MyWindow");
694*61046927SAndroid Build Coastguard Worker        Button("Play");        // Label = "Play",   ID = hash of ("MyWindow", "Play")
695*61046927SAndroid Build Coastguard Worker        Button("Play##foo1");  // Label = "Play",   ID = hash of ("MyWindow", "Play##foo1")  // Different from above
696*61046927SAndroid Build Coastguard Worker        Button("Play##foo2");  // Label = "Play",   ID = hash of ("MyWindow", "Play##foo2")  // Different from above
697*61046927SAndroid Build Coastguard Worker        End();
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker    - If you want to completely hide the label, but still need an ID:
700*61046927SAndroid Build Coastguard Worker 
701*61046927SAndroid Build Coastguard Worker        Checkbox("##On", &b);  // Label = "",       ID = hash of (..., "##On")   // No visible label, just a checkbox!
702*61046927SAndroid Build Coastguard Worker 
703*61046927SAndroid Build Coastguard Worker    - Occasionally/rarely you might want change a label while preserving a constant ID. This allows
704*61046927SAndroid Build Coastguard Worker      you to animate labels. For example you may want to include varying information in a window title bar,
705*61046927SAndroid Build Coastguard Worker      but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker        Button("Hello###ID");  // Label = "Hello",  ID = hash of (..., "###ID")
708*61046927SAndroid Build Coastguard Worker        Button("World###ID");  // Label = "World",  ID = hash of (..., "###ID")  // Same as above, even though the label looks different
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker        sprintf(buf, "My game (%f FPS)###MyGame", fps);
711*61046927SAndroid Build Coastguard Worker        Begin(buf);            // Variable title,   ID = hash of "MyGame"
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker    - Solving ID conflict in a more general manner:
714*61046927SAndroid Build Coastguard Worker      Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
715*61046927SAndroid Build Coastguard Worker      within the same window. This is the most convenient way of distinguishing ID when iterating and
716*61046927SAndroid Build Coastguard Worker      creating many UI elements programmatically.
717*61046927SAndroid Build Coastguard Worker      You can push a pointer, a string or an integer value into the ID stack.
718*61046927SAndroid Build Coastguard Worker      Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
719*61046927SAndroid Build Coastguard Worker      At each level of the stack we store the seed used for items at this level of the ID stack.
720*61046927SAndroid Build Coastguard Worker 
721*61046927SAndroid Build Coastguard Worker      Begin("Window");
722*61046927SAndroid Build Coastguard Worker        for (int i = 0; i < 100; i++)
723*61046927SAndroid Build Coastguard Worker        {
724*61046927SAndroid Build Coastguard Worker          PushID(i);           // Push i to the id tack
725*61046927SAndroid Build Coastguard Worker          Button("Click");     // Label = "Click",  ID = hash of ("Window", i, "Click")
726*61046927SAndroid Build Coastguard Worker          PopID();
727*61046927SAndroid Build Coastguard Worker        }
728*61046927SAndroid Build Coastguard Worker        for (int i = 0; i < 100; i++)
729*61046927SAndroid Build Coastguard Worker        {
730*61046927SAndroid Build Coastguard Worker          MyObject* obj = Objects[i];
731*61046927SAndroid Build Coastguard Worker          PushID(obj);
732*61046927SAndroid Build Coastguard Worker          Button("Click");     // Label = "Click",  ID = hash of ("Window", obj pointer, "Click")
733*61046927SAndroid Build Coastguard Worker          PopID();
734*61046927SAndroid Build Coastguard Worker        }
735*61046927SAndroid Build Coastguard Worker        for (int i = 0; i < 100; i++)
736*61046927SAndroid Build Coastguard Worker        {
737*61046927SAndroid Build Coastguard Worker          MyObject* obj = Objects[i];
738*61046927SAndroid Build Coastguard Worker          PushID(obj->Name);
739*61046927SAndroid Build Coastguard Worker          Button("Click");     // Label = "Click",  ID = hash of ("Window", obj->Name, "Click")
740*61046927SAndroid Build Coastguard Worker          PopID();
741*61046927SAndroid Build Coastguard Worker        }
742*61046927SAndroid Build Coastguard Worker        End();
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    - You can stack multiple prefixes into the ID stack:
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker        Button("Click");       // Label = "Click",  ID = hash of (..., "Click")
747*61046927SAndroid Build Coastguard Worker        PushID("node");
748*61046927SAndroid Build Coastguard Worker        Button("Click");       // Label = "Click",  ID = hash of (..., "node", "Click")
749*61046927SAndroid Build Coastguard Worker          PushID(my_ptr);
750*61046927SAndroid Build Coastguard Worker            Button("Click");   // Label = "Click",  ID = hash of (..., "node", my_ptr, "Click")
751*61046927SAndroid Build Coastguard Worker          PopID();
752*61046927SAndroid Build Coastguard Worker        PopID();
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker    - Tree nodes implicitly creates a scope for you by calling PushID().
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker        Button("Click");       // Label = "Click",  ID = hash of (..., "Click")
757*61046927SAndroid Build Coastguard Worker        if (TreeNode("node"))  // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
758*61046927SAndroid Build Coastguard Worker        {
759*61046927SAndroid Build Coastguard Worker          Button("Click");     // Label = "Click",  ID = hash of (..., "node", "Click")
760*61046927SAndroid Build Coastguard Worker          TreePop();
761*61046927SAndroid Build Coastguard Worker        }
762*61046927SAndroid Build Coastguard Worker 
763*61046927SAndroid Build Coastguard Worker    - When working with trees, ID are used to preserve the open/close state of each tree node.
764*61046927SAndroid Build Coastguard Worker      Depending on your use cases you may want to use strings, indices or pointers as ID.
765*61046927SAndroid Build Coastguard Worker       e.g. when following a single pointer that may change over time, using a static string as ID
766*61046927SAndroid Build Coastguard Worker        will preserve your node open/closed state when the targeted object change.
767*61046927SAndroid Build Coastguard Worker       e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
768*61046927SAndroid Build Coastguard Worker        node open/closed state differently. See what makes more sense in your situation!
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker  Q: How can I use my own math types instead of ImVec2/ImVec4?
771*61046927SAndroid Build Coastguard Worker  A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions.
772*61046927SAndroid Build Coastguard Worker     This way you'll be able to use your own types everywhere, e.g. passsing glm::vec2 to ImGui functions instead of ImVec2.
773*61046927SAndroid Build Coastguard Worker 
774*61046927SAndroid Build Coastguard Worker  Q: How can I load a different font than the default?
775*61046927SAndroid Build Coastguard Worker  A: Use the font atlas to load the TTF/OTF file you want:
776*61046927SAndroid Build Coastguard Worker       ImGuiIO& io = ImGui::GetIO();
777*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
778*61046927SAndroid Build Coastguard Worker       io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
779*61046927SAndroid Build Coastguard Worker     Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
780*61046927SAndroid Build Coastguard Worker     (Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
781*61046927SAndroid Build Coastguard Worker     (Read the 'misc/fonts/README.txt' file for more details about font loading.)
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker     New programmers: remember that in C/C++ and most programming languages if you want to use a
784*61046927SAndroid Build Coastguard Worker     backslash \ within a string literal, you need to write it double backslash "\\":
785*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels);   // WRONG (you are escape the M here!)
786*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels);  // CORRECT
787*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels);   // ALSO CORRECT
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker  Q: How can I easily use icons in my application?
790*61046927SAndroid Build Coastguard Worker  A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you
791*61046927SAndroid Build Coastguard Worker     main font. Then you can refer to icons within your strings.
792*61046927SAndroid Build Coastguard Worker     You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment.
793*61046927SAndroid Build Coastguard Worker     (Read the 'misc/fonts/README.txt' file for more details about icons font loading.)
794*61046927SAndroid Build Coastguard Worker 
795*61046927SAndroid Build Coastguard Worker  Q: How can I load multiple fonts?
796*61046927SAndroid Build Coastguard Worker  A: Use the font atlas to pack them into a single texture:
797*61046927SAndroid Build Coastguard Worker     (Read the 'misc/fonts/README.txt' file and the code in ImFontAtlas for more details.)
798*61046927SAndroid Build Coastguard Worker 
799*61046927SAndroid Build Coastguard Worker       ImGuiIO& io = ImGui::GetIO();
800*61046927SAndroid Build Coastguard Worker       ImFont* font0 = io.Fonts->AddFontDefault();
801*61046927SAndroid Build Coastguard Worker       ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
802*61046927SAndroid Build Coastguard Worker       ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
803*61046927SAndroid Build Coastguard Worker       io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
804*61046927SAndroid Build Coastguard Worker       // the first loaded font gets used by default
805*61046927SAndroid Build Coastguard Worker       // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker       // Options
808*61046927SAndroid Build Coastguard Worker       ImFontConfig config;
809*61046927SAndroid Build Coastguard Worker       config.OversampleH = 2;
810*61046927SAndroid Build Coastguard Worker       config.OversampleV = 1;
811*61046927SAndroid Build Coastguard Worker       config.GlyphOffset.y -= 1.0f;      // Move everything by 1 pixels up
812*61046927SAndroid Build Coastguard Worker       config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
813*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker       // Combine multiple fonts into one (e.g. for icon fonts)
816*61046927SAndroid Build Coastguard Worker       static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
817*61046927SAndroid Build Coastguard Worker       ImFontConfig config;
818*61046927SAndroid Build Coastguard Worker       config.MergeMode = true;
819*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontDefault();
820*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
821*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker  Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
824*61046927SAndroid Build Coastguard Worker  A: When loading a font, pass custom Unicode ranges to specify the glyphs to load.
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker       // Add default Japanese ranges
827*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
828*61046927SAndroid Build Coastguard Worker 
829*61046927SAndroid Build Coastguard Worker       // 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)
830*61046927SAndroid Build Coastguard Worker       ImVector<ImWchar> ranges;
831*61046927SAndroid Build Coastguard Worker       ImFontGlyphRangesBuilder builder;
832*61046927SAndroid Build Coastguard Worker       builder.AddText("Hello world");                        // Add a string (here "Hello world" contains 7 unique characters)
833*61046927SAndroid Build Coastguard Worker       builder.AddChar(0x7262);                               // Add a specific character
834*61046927SAndroid Build Coastguard Worker       builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
835*61046927SAndroid Build Coastguard Worker       builder.BuildRanges(&ranges);                          // Build the final result (ordered ranges with all the unique characters submitted)
836*61046927SAndroid Build Coastguard Worker       io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker     All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
839*61046927SAndroid Build Coastguard Worker     by using the u8"hello" syntax. Specifying literal in your source code using a local code page
840*61046927SAndroid Build Coastguard Worker     (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
841*61046927SAndroid Build Coastguard Worker     Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
842*61046927SAndroid Build Coastguard Worker 
843*61046927SAndroid Build Coastguard Worker     Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter().
844*61046927SAndroid Build Coastguard Worker     The applications in examples/ are doing that.
845*61046927SAndroid Build Coastguard Worker     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).
846*61046927SAndroid Build Coastguard Worker     You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
847*61046927SAndroid Build Coastguard Worker     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
848*61046927SAndroid Build Coastguard Worker     the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
849*61046927SAndroid Build Coastguard Worker 
850*61046927SAndroid Build Coastguard Worker  Q: How can I interact with standard C++ types (such as std::string and std::vector)?
851*61046927SAndroid Build Coastguard Worker  A: - Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers),
852*61046927SAndroid Build Coastguard Worker       and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use
853*61046927SAndroid Build Coastguard Worker       any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
854*61046927SAndroid Build Coastguard Worker     - To use ImGui::InputText() with a std::string or any resizable string class, see misc/cpp/imgui_stdlib.h.
855*61046927SAndroid Build Coastguard Worker     - To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API
856*61046927SAndroid Build Coastguard Worker       lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API.
857*61046927SAndroid Build Coastguard Worker       Prefer using them over the old and awkward Combo()/ListBox() api.
858*61046927SAndroid Build Coastguard Worker     - Generally for most high-level types you should be able to access the underlying data type.
859*61046927SAndroid Build Coastguard Worker       You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
860*61046927SAndroid Build Coastguard Worker     - Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
861*61046927SAndroid Build Coastguard Worker       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.
862*61046927SAndroid Build Coastguard Worker       Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances.
863*61046927SAndroid Build Coastguard Worker       Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those
864*61046927SAndroid Build Coastguard Worker       are not configurable and not the same across implementations.
865*61046927SAndroid Build Coastguard Worker     - If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
866*61046927SAndroid Build Coastguard Worker       of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
867*61046927SAndroid Build Coastguard Worker       is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
868*61046927SAndroid Build Coastguard Worker       One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
869*61046927SAndroid Build Coastguard Worker       This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
870*61046927SAndroid Build Coastguard Worker       provide similar or better string helpers.
871*61046927SAndroid Build Coastguard Worker 
872*61046927SAndroid Build Coastguard Worker  Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
873*61046927SAndroid Build Coastguard Worker  A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags.
874*61046927SAndroid Build Coastguard Worker       (The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse)
875*61046927SAndroid Build Coastguard Worker       Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
876*61046927SAndroid Build Coastguard Worker     - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows.
877*61046927SAndroid Build Coastguard Worker     - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create
878*61046927SAndroid Build Coastguard Worker       your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data.
879*61046927SAndroid Build Coastguard Worker 
880*61046927SAndroid Build Coastguard Worker  Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
881*61046927SAndroid Build Coastguard Worker  A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
882*61046927SAndroid Build Coastguard Worker       (short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad)
883*61046927SAndroid Build Coastguard Worker     - You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy)
884*61046927SAndroid Build Coastguard Worker       This is the preferred solution for developer productivity.
885*61046927SAndroid Build Coastguard Worker       In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple
886*61046927SAndroid Build Coastguard Worker       and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
887*61046927SAndroid Build Coastguard Worker       to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
888*61046927SAndroid Build Coastguard Worker       Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
889*61046927SAndroid Build Coastguard Worker     - You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends
890*61046927SAndroid Build Coastguard Worker       the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine.
891*61046927SAndroid Build Coastguard Worker     - For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate
892*61046927SAndroid Build Coastguard Worker       for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
893*61046927SAndroid Build Coastguard Worker       for screen real-estate and precision.
894*61046927SAndroid Build Coastguard Worker 
895*61046927SAndroid Build Coastguard Worker  Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
896*61046927SAndroid Build Coastguard Worker  A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
897*61046927SAndroid Build Coastguard Worker     Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
898*61046927SAndroid Build Coastguard Worker 
899*61046927SAndroid Build Coastguard Worker  Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
900*61046927SAndroid Build Coastguard Worker  A: You are probably mishandling the clipping rectangles in your render function.
901*61046927SAndroid Build Coastguard Worker     Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
902*61046927SAndroid Build Coastguard Worker 
903*61046927SAndroid Build Coastguard Worker  Q: How can I help?
904*61046927SAndroid Build Coastguard Worker  A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt
905*61046927SAndroid Build Coastguard Worker       and see how you want to help and can help!
906*61046927SAndroid Build Coastguard Worker     - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui.
907*61046927SAndroid Build Coastguard Worker     - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README.
908*61046927SAndroid Build Coastguard Worker     - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
909*61046927SAndroid Build Coastguard Worker       You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers.
910*61046927SAndroid Build Coastguard Worker       But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
911*61046927SAndroid Build Coastguard Worker     - 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).
912*61046927SAndroid Build Coastguard Worker 
913*61046927SAndroid Build Coastguard Worker  - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
914*61046927SAndroid Build Coastguard Worker         this is also useful to set yourself in the context of another window (to get/set other settings)
915*61046927SAndroid Build Coastguard Worker  - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
916*61046927SAndroid Build Coastguard Worker  - 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
917*61046927SAndroid Build Coastguard Worker         of a deep nested inner loop in your code.
918*61046927SAndroid Build Coastguard Worker  - tip: you can call Render() multiple times (e.g for VR renders).
919*61046927SAndroid Build Coastguard Worker  - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui!
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker */
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
924*61046927SAndroid Build Coastguard Worker #define _CRT_SECURE_NO_WARNINGS
925*61046927SAndroid Build Coastguard Worker #endif
926*61046927SAndroid Build Coastguard Worker 
927*61046927SAndroid Build Coastguard Worker #include "imgui.h"
928*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DEFINE_MATH_OPERATORS
929*61046927SAndroid Build Coastguard Worker #define IMGUI_DEFINE_MATH_OPERATORS
930*61046927SAndroid Build Coastguard Worker #endif
931*61046927SAndroid Build Coastguard Worker #include "imgui_internal.h"
932*61046927SAndroid Build Coastguard Worker 
933*61046927SAndroid Build Coastguard Worker #include <ctype.h>      // toupper, isprint
934*61046927SAndroid Build Coastguard Worker #include <stdio.h>      // vsnprintf, sscanf, printf
935*61046927SAndroid Build Coastguard Worker #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
936*61046927SAndroid Build Coastguard Worker #include <stddef.h>     // intptr_t
937*61046927SAndroid Build Coastguard Worker #else
938*61046927SAndroid Build Coastguard Worker #include <stdint.h>     // intptr_t
939*61046927SAndroid Build Coastguard Worker #endif
940*61046927SAndroid Build Coastguard Worker 
941*61046927SAndroid Build Coastguard Worker // Debug options
942*61046927SAndroid Build Coastguard Worker #define IMGUI_DEBUG_NAV_SCORING     0   // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL
943*61046927SAndroid Build Coastguard Worker #define IMGUI_DEBUG_NAV_RECTS       0   // Display the reference navigation rectangle for each window
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker // Visual Studio warnings
946*61046927SAndroid Build Coastguard Worker #ifdef _MSC_VER
947*61046927SAndroid Build Coastguard Worker #pragma warning (disable: 4127)     // condition expression is constant
948*61046927SAndroid Build Coastguard Worker #pragma warning (disable: 4996)     // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
949*61046927SAndroid Build Coastguard Worker #endif
950*61046927SAndroid Build Coastguard Worker 
951*61046927SAndroid Build Coastguard Worker // Clang/GCC warnings with -Weverything
952*61046927SAndroid Build Coastguard Worker #ifdef __clang__
953*61046927SAndroid Build Coastguard Worker #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!
954*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wold-style-cast"         // warning : use of old-style cast                              // yes, they are more terse.
955*61046927SAndroid Build Coastguard Worker #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.
956*61046927SAndroid Build Coastguard Worker #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.
957*61046927SAndroid Build Coastguard Worker #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.
958*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wglobal-constructors"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.
959*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wsign-conversion"        // warning : implicit conversion changes signedness             //
960*61046927SAndroid Build Coastguard Worker #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.
961*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning : cast to 'void *' from smaller integer type 'int'
962*61046927SAndroid Build Coastguard Worker #if __has_warning("-Wzero-as-null-pointer-constant")
963*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning : zero as null pointer constant              // some standard header variations use #define NULL 0
964*61046927SAndroid Build Coastguard Worker #endif
965*61046927SAndroid Build Coastguard Worker #if __has_warning("-Wdouble-promotion")
966*61046927SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdouble-promotion"       // warning: implicit conversion from 'float' to 'double' when passing argument to function  // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
967*61046927SAndroid Build Coastguard Worker #endif
968*61046927SAndroid Build Coastguard Worker #elif defined(__GNUC__)
969*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
970*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
971*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wformat"                   // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
972*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
973*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
974*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wformat-nonliteral"        // warning: format not a string literal, format string not checked
975*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wstrict-overflow"          // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
976*61046927SAndroid Build Coastguard Worker #if __GNUC__ >= 8
977*61046927SAndroid Build Coastguard Worker #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
978*61046927SAndroid Build Coastguard Worker #endif
979*61046927SAndroid Build Coastguard Worker #endif
980*61046927SAndroid Build Coastguard Worker 
981*61046927SAndroid Build Coastguard Worker // 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.
982*61046927SAndroid Build Coastguard Worker static const float NAV_WINDOWING_HIGHLIGHT_DELAY            = 0.20f;    // Time before the highlight and screen dimming starts fading in
983*61046927SAndroid Build Coastguard Worker static const float NAV_WINDOWING_LIST_APPEAR_DELAY          = 0.15f;    // Time before the window list starts to appear
984*61046927SAndroid Build Coastguard Worker 
985*61046927SAndroid Build Coastguard Worker // Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end)
986*61046927SAndroid Build Coastguard Worker static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f;     // Extend outside and inside windows. Affect FindHoveredWindow().
987*61046927SAndroid Build Coastguard Worker static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;    // Reduce visual noise by only highlighting the border after a certain time.
988*61046927SAndroid Build Coastguard Worker 
989*61046927SAndroid Build Coastguard Worker //-------------------------------------------------------------------------
990*61046927SAndroid Build Coastguard Worker // [SECTION] FORWARD DECLARATIONS
991*61046927SAndroid Build Coastguard Worker //-------------------------------------------------------------------------
992*61046927SAndroid Build Coastguard Worker 
993*61046927SAndroid Build Coastguard Worker static void             SetCurrentWindow(ImGuiWindow* window);
994*61046927SAndroid Build Coastguard Worker static void             FindHoveredWindow();
995*61046927SAndroid Build Coastguard Worker static ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
996*61046927SAndroid Build Coastguard Worker static void             CheckStacksSize(ImGuiWindow* window, bool write);
997*61046927SAndroid Build Coastguard Worker static ImVec2           CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
998*61046927SAndroid Build Coastguard Worker 
999*61046927SAndroid Build Coastguard Worker static void             AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
1000*61046927SAndroid Build Coastguard Worker static void             AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker static ImRect           GetViewportRect();
1003*61046927SAndroid Build Coastguard Worker 
1004*61046927SAndroid Build Coastguard Worker // Settings
1005*61046927SAndroid Build Coastguard Worker static void*            SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
1006*61046927SAndroid Build Coastguard Worker static void             SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
1007*61046927SAndroid Build Coastguard Worker static void             SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
1008*61046927SAndroid Build Coastguard Worker 
1009*61046927SAndroid Build Coastguard Worker // Platform Dependents default implementation for IO functions
1010*61046927SAndroid Build Coastguard Worker static const char*      GetClipboardTextFn_DefaultImpl(void* user_data);
1011*61046927SAndroid Build Coastguard Worker static void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
1012*61046927SAndroid Build Coastguard Worker static void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
1013*61046927SAndroid Build Coastguard Worker 
1014*61046927SAndroid Build Coastguard Worker namespace ImGui
1015*61046927SAndroid Build Coastguard Worker {
1016*61046927SAndroid Build Coastguard Worker static bool             BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker // Navigation
1019*61046927SAndroid Build Coastguard Worker static void             NavUpdate();
1020*61046927SAndroid Build Coastguard Worker static void             NavUpdateWindowing();
1021*61046927SAndroid Build Coastguard Worker static void             NavUpdateWindowingList();
1022*61046927SAndroid Build Coastguard Worker static void             NavUpdateMoveResult();
1023*61046927SAndroid Build Coastguard Worker static float            NavUpdatePageUpPageDown(int allowed_dir_flags);
1024*61046927SAndroid Build Coastguard Worker static inline void      NavUpdateAnyRequestFlag();
1025*61046927SAndroid Build Coastguard Worker static void             NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
1026*61046927SAndroid Build Coastguard Worker static ImVec2           NavCalcPreferredRefPos();
1027*61046927SAndroid Build Coastguard Worker static void             NavSaveLastChildNavWindow(ImGuiWindow* nav_window);
1028*61046927SAndroid Build Coastguard Worker static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
1029*61046927SAndroid Build Coastguard Worker 
1030*61046927SAndroid Build Coastguard Worker // Misc
1031*61046927SAndroid Build Coastguard Worker static void             UpdateMouseInputs();
1032*61046927SAndroid Build Coastguard Worker static void             UpdateMouseWheel();
1033*61046927SAndroid Build Coastguard Worker static void             UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
1034*61046927SAndroid Build Coastguard Worker static void             RenderOuterBorders(ImGuiWindow* window);
1035*61046927SAndroid Build Coastguard Worker 
1036*61046927SAndroid Build Coastguard Worker }
1037*61046927SAndroid Build Coastguard Worker 
1038*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1039*61046927SAndroid Build Coastguard Worker // [SECTION] CONTEXT AND MEMORY ALLOCATORS
1040*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1041*61046927SAndroid Build Coastguard Worker 
1042*61046927SAndroid Build Coastguard Worker // Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
1043*61046927SAndroid Build Coastguard Worker // ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
1044*61046927SAndroid Build Coastguard Worker // 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call
1045*61046927SAndroid Build Coastguard Worker //    SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading.
1046*61046927SAndroid Build Coastguard Worker //    In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into.
1047*61046927SAndroid Build Coastguard Worker // 2) Important: Dear ImGui functions are not thread-safe because of this pointer.
1048*61046927SAndroid Build Coastguard Worker //    If you want thread-safety to allow N threads to access N different contexts, you can:
1049*61046927SAndroid Build Coastguard Worker //    - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h:
1050*61046927SAndroid Build Coastguard Worker //          struct ImGuiContext;
1051*61046927SAndroid Build Coastguard Worker //          extern thread_local ImGuiContext* MyImGuiTLS;
1052*61046927SAndroid Build Coastguard Worker //          #define GImGui MyImGuiTLS
1053*61046927SAndroid Build Coastguard Worker //      And then define MyImGuiTLS in one of your cpp file. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
1054*61046927SAndroid Build Coastguard Worker //    - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
1055*61046927SAndroid Build Coastguard Worker //    - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
1056*61046927SAndroid Build Coastguard Worker #ifndef GImGui
1057*61046927SAndroid Build Coastguard Worker ImGuiContext*   GImGui = NULL;
1058*61046927SAndroid Build Coastguard Worker #endif
1059*61046927SAndroid Build Coastguard Worker 
1060*61046927SAndroid Build Coastguard Worker // Memory Allocator functions. Use SetAllocatorFunctions() to change them.
1061*61046927SAndroid Build Coastguard Worker // If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
1062*61046927SAndroid Build Coastguard Worker // 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.
1063*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
MallocWrapper(size_t size,void * user_data)1064*61046927SAndroid Build Coastguard Worker static void*   MallocWrapper(size_t size, void* user_data)    { IM_UNUSED(user_data); return malloc(size); }
FreeWrapper(void * ptr,void * user_data)1065*61046927SAndroid Build Coastguard Worker static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_data); free(ptr); }
1066*61046927SAndroid Build Coastguard Worker #else
MallocWrapper(size_t size,void * user_data)1067*61046927SAndroid Build Coastguard Worker static void*   MallocWrapper(size_t size, void* user_data)    { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
FreeWrapper(void * ptr,void * user_data)1068*61046927SAndroid Build Coastguard Worker static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
1069*61046927SAndroid Build Coastguard Worker #endif
1070*61046927SAndroid Build Coastguard Worker 
1071*61046927SAndroid Build Coastguard Worker static void*  (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
1072*61046927SAndroid Build Coastguard Worker static void   (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
1073*61046927SAndroid Build Coastguard Worker static void*    GImAllocatorUserData = NULL;
1074*61046927SAndroid Build Coastguard Worker 
1075*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1076*61046927SAndroid Build Coastguard Worker // [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
1077*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1078*61046927SAndroid Build Coastguard Worker 
ImGuiStyle()1079*61046927SAndroid Build Coastguard Worker ImGuiStyle::ImGuiStyle()
1080*61046927SAndroid Build Coastguard Worker {
1081*61046927SAndroid Build Coastguard Worker     Alpha                   = 1.0f;             // Global alpha applies to everything in ImGui
1082*61046927SAndroid Build Coastguard Worker     WindowPadding           = ImVec2(8,8);      // Padding within a window
1083*61046927SAndroid Build Coastguard Worker     WindowRounding          = 7.0f;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows
1084*61046927SAndroid Build Coastguard Worker     WindowBorderSize        = 1.0f;             // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1085*61046927SAndroid Build Coastguard Worker     WindowMinSize           = ImVec2(32,32);    // Minimum window size
1086*61046927SAndroid Build Coastguard Worker     WindowTitleAlign        = ImVec2(0.0f,0.5f);// Alignment for title bar text
1087*61046927SAndroid Build Coastguard Worker     ChildRounding           = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
1088*61046927SAndroid Build Coastguard Worker     ChildBorderSize         = 1.0f;             // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1089*61046927SAndroid Build Coastguard Worker     PopupRounding           = 0.0f;             // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
1090*61046927SAndroid Build Coastguard Worker     PopupBorderSize         = 1.0f;             // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
1091*61046927SAndroid Build Coastguard Worker     FramePadding            = ImVec2(4,3);      // Padding within a framed rectangle (used by most widgets)
1092*61046927SAndroid Build Coastguard Worker     FrameRounding           = 0.0f;             // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
1093*61046927SAndroid Build Coastguard Worker     FrameBorderSize         = 0.0f;             // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
1094*61046927SAndroid Build Coastguard Worker     ItemSpacing             = ImVec2(8,4);      // Horizontal and vertical spacing between widgets/lines
1095*61046927SAndroid Build Coastguard Worker     ItemInnerSpacing        = ImVec2(4,4);      // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
1096*61046927SAndroid Build Coastguard Worker     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!
1097*61046927SAndroid Build Coastguard Worker     IndentSpacing           = 21.0f;            // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
1098*61046927SAndroid Build Coastguard Worker     ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
1099*61046927SAndroid Build Coastguard Worker     ScrollbarSize           = 16.0f;            // Width of the vertical scrollbar, Height of the horizontal scrollbar
1100*61046927SAndroid Build Coastguard Worker     ScrollbarRounding       = 9.0f;             // Radius of grab corners rounding for scrollbar
1101*61046927SAndroid Build Coastguard Worker     GrabMinSize             = 10.0f;            // Minimum width/height of a grab box for slider/scrollbar
1102*61046927SAndroid Build Coastguard Worker     GrabRounding            = 0.0f;             // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
1103*61046927SAndroid Build Coastguard Worker     TabRounding             = 4.0f;             // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
1104*61046927SAndroid Build Coastguard Worker     TabBorderSize           = 0.0f;             // Thickness of border around tabs.
1105*61046927SAndroid Build Coastguard Worker     ButtonTextAlign         = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
1106*61046927SAndroid Build Coastguard Worker     SelectableTextAlign     = ImVec2(0.0f,0.0f);// Alignment of selectable text when button is larger than text.
1107*61046927SAndroid Build Coastguard Worker     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.
1108*61046927SAndroid Build Coastguard Worker     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.
1109*61046927SAndroid Build Coastguard Worker     MouseCursorScale        = 1.0f;             // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
1110*61046927SAndroid Build Coastguard Worker     AntiAliasedLines        = true;             // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
1111*61046927SAndroid Build Coastguard Worker     AntiAliasedFill         = true;             // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
1112*61046927SAndroid Build Coastguard Worker     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.
1113*61046927SAndroid Build Coastguard Worker 
1114*61046927SAndroid Build Coastguard Worker     // Default theme
1115*61046927SAndroid Build Coastguard Worker     ImGui::StyleColorsDark(this);
1116*61046927SAndroid Build Coastguard Worker }
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker // 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.
1119*61046927SAndroid Build Coastguard Worker // 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.
ScaleAllSizes(float scale_factor)1120*61046927SAndroid Build Coastguard Worker void ImGuiStyle::ScaleAllSizes(float scale_factor)
1121*61046927SAndroid Build Coastguard Worker {
1122*61046927SAndroid Build Coastguard Worker     WindowPadding = ImFloor(WindowPadding * scale_factor);
1123*61046927SAndroid Build Coastguard Worker     WindowRounding = ImFloor(WindowRounding * scale_factor);
1124*61046927SAndroid Build Coastguard Worker     WindowMinSize = ImFloor(WindowMinSize * scale_factor);
1125*61046927SAndroid Build Coastguard Worker     ChildRounding = ImFloor(ChildRounding * scale_factor);
1126*61046927SAndroid Build Coastguard Worker     PopupRounding = ImFloor(PopupRounding * scale_factor);
1127*61046927SAndroid Build Coastguard Worker     FramePadding = ImFloor(FramePadding * scale_factor);
1128*61046927SAndroid Build Coastguard Worker     FrameRounding = ImFloor(FrameRounding * scale_factor);
1129*61046927SAndroid Build Coastguard Worker     ItemSpacing = ImFloor(ItemSpacing * scale_factor);
1130*61046927SAndroid Build Coastguard Worker     ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
1131*61046927SAndroid Build Coastguard Worker     TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
1132*61046927SAndroid Build Coastguard Worker     IndentSpacing = ImFloor(IndentSpacing * scale_factor);
1133*61046927SAndroid Build Coastguard Worker     ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
1134*61046927SAndroid Build Coastguard Worker     ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
1135*61046927SAndroid Build Coastguard Worker     ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
1136*61046927SAndroid Build Coastguard Worker     GrabMinSize = ImFloor(GrabMinSize * scale_factor);
1137*61046927SAndroid Build Coastguard Worker     GrabRounding = ImFloor(GrabRounding * scale_factor);
1138*61046927SAndroid Build Coastguard Worker     TabRounding = ImFloor(TabRounding * scale_factor);
1139*61046927SAndroid Build Coastguard Worker     DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
1140*61046927SAndroid Build Coastguard Worker     DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
1141*61046927SAndroid Build Coastguard Worker     MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
1142*61046927SAndroid Build Coastguard Worker }
1143*61046927SAndroid Build Coastguard Worker 
ImGuiIO()1144*61046927SAndroid Build Coastguard Worker ImGuiIO::ImGuiIO()
1145*61046927SAndroid Build Coastguard Worker {
1146*61046927SAndroid Build Coastguard Worker     // Most fields are initialized with zero
1147*61046927SAndroid Build Coastguard Worker     memset(this, 0, sizeof(*this));
1148*61046927SAndroid Build Coastguard Worker 
1149*61046927SAndroid Build Coastguard Worker     // Settings
1150*61046927SAndroid Build Coastguard Worker     ConfigFlags = ImGuiConfigFlags_None;
1151*61046927SAndroid Build Coastguard Worker     BackendFlags = ImGuiBackendFlags_None;
1152*61046927SAndroid Build Coastguard Worker     DisplaySize = ImVec2(-1.0f, -1.0f);
1153*61046927SAndroid Build Coastguard Worker     DeltaTime = 1.0f/60.0f;
1154*61046927SAndroid Build Coastguard Worker     IniSavingRate = 5.0f;
1155*61046927SAndroid Build Coastguard Worker     IniFilename = "imgui.ini";
1156*61046927SAndroid Build Coastguard Worker     LogFilename = "imgui_log.txt";
1157*61046927SAndroid Build Coastguard Worker     MouseDoubleClickTime = 0.30f;
1158*61046927SAndroid Build Coastguard Worker     MouseDoubleClickMaxDist = 6.0f;
1159*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < ImGuiKey_COUNT; i++)
1160*61046927SAndroid Build Coastguard Worker         KeyMap[i] = -1;
1161*61046927SAndroid Build Coastguard Worker     KeyRepeatDelay = 0.250f;
1162*61046927SAndroid Build Coastguard Worker     KeyRepeatRate = 0.050f;
1163*61046927SAndroid Build Coastguard Worker     UserData = NULL;
1164*61046927SAndroid Build Coastguard Worker 
1165*61046927SAndroid Build Coastguard Worker     Fonts = NULL;
1166*61046927SAndroid Build Coastguard Worker     FontGlobalScale = 1.0f;
1167*61046927SAndroid Build Coastguard Worker     FontDefault = NULL;
1168*61046927SAndroid Build Coastguard Worker     FontAllowUserScaling = false;
1169*61046927SAndroid Build Coastguard Worker     DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
1170*61046927SAndroid Build Coastguard Worker 
1171*61046927SAndroid Build Coastguard Worker     // Miscellaneous options
1172*61046927SAndroid Build Coastguard Worker     MouseDrawCursor = false;
1173*61046927SAndroid Build Coastguard Worker #ifdef __APPLE__
1174*61046927SAndroid Build Coastguard Worker     ConfigMacOSXBehaviors = true;  // Set Mac OS X style defaults based on __APPLE__ compile time flag
1175*61046927SAndroid Build Coastguard Worker #else
1176*61046927SAndroid Build Coastguard Worker     ConfigMacOSXBehaviors = false;
1177*61046927SAndroid Build Coastguard Worker #endif
1178*61046927SAndroid Build Coastguard Worker     ConfigInputTextCursorBlink = true;
1179*61046927SAndroid Build Coastguard Worker     ConfigWindowsResizeFromEdges = true;
1180*61046927SAndroid Build Coastguard Worker     ConfigWindowsMoveFromTitleBarOnly = false;
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker     // Platform Functions
1183*61046927SAndroid Build Coastguard Worker     BackendPlatformName = BackendRendererName = NULL;
1184*61046927SAndroid Build Coastguard Worker     BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
1185*61046927SAndroid Build Coastguard Worker     GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations
1186*61046927SAndroid Build Coastguard Worker     SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
1187*61046927SAndroid Build Coastguard Worker     ClipboardUserData = NULL;
1188*61046927SAndroid Build Coastguard Worker     ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
1189*61046927SAndroid Build Coastguard Worker     ImeWindowHandle = NULL;
1190*61046927SAndroid Build Coastguard Worker 
1191*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1192*61046927SAndroid Build Coastguard Worker     RenderDrawListsFn = NULL;
1193*61046927SAndroid Build Coastguard Worker #endif
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker     // Input (NB: we already have memset zero the entire structure!)
1196*61046927SAndroid Build Coastguard Worker     MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
1197*61046927SAndroid Build Coastguard Worker     MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
1198*61046927SAndroid Build Coastguard Worker     MouseDragThreshold = 6.0f;
1199*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
1200*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i]  = KeysDownDurationPrev[i] = -1.0f;
1201*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
1202*61046927SAndroid Build Coastguard Worker }
1203*61046927SAndroid Build Coastguard Worker 
1204*61046927SAndroid Build Coastguard Worker // Pass in translated ASCII characters for text input.
1205*61046927SAndroid Build Coastguard Worker // - with glfw you can get those from the callback set in glfwSetCharCallback()
1206*61046927SAndroid Build Coastguard Worker // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
AddInputCharacter(ImWchar c)1207*61046927SAndroid Build Coastguard Worker void ImGuiIO::AddInputCharacter(ImWchar c)
1208*61046927SAndroid Build Coastguard Worker {
1209*61046927SAndroid Build Coastguard Worker     InputQueueCharacters.push_back(c);
1210*61046927SAndroid Build Coastguard Worker }
1211*61046927SAndroid Build Coastguard Worker 
AddInputCharactersUTF8(const char * utf8_chars)1212*61046927SAndroid Build Coastguard Worker void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
1213*61046927SAndroid Build Coastguard Worker {
1214*61046927SAndroid Build Coastguard Worker     while (*utf8_chars != 0)
1215*61046927SAndroid Build Coastguard Worker     {
1216*61046927SAndroid Build Coastguard Worker         unsigned int c = 0;
1217*61046927SAndroid Build Coastguard Worker         utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
1218*61046927SAndroid Build Coastguard Worker         if (c > 0 && c <= 0xFFFF)
1219*61046927SAndroid Build Coastguard Worker             InputQueueCharacters.push_back((ImWchar)c);
1220*61046927SAndroid Build Coastguard Worker     }
1221*61046927SAndroid Build Coastguard Worker }
1222*61046927SAndroid Build Coastguard Worker 
ClearInputCharacters()1223*61046927SAndroid Build Coastguard Worker void ImGuiIO::ClearInputCharacters()
1224*61046927SAndroid Build Coastguard Worker {
1225*61046927SAndroid Build Coastguard Worker     InputQueueCharacters.resize(0);
1226*61046927SAndroid Build Coastguard Worker }
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1229*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
1230*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1231*61046927SAndroid Build Coastguard Worker 
ImLineClosestPoint(const ImVec2 & a,const ImVec2 & b,const ImVec2 & p)1232*61046927SAndroid Build Coastguard Worker ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
1233*61046927SAndroid Build Coastguard Worker {
1234*61046927SAndroid Build Coastguard Worker     ImVec2 ap = p - a;
1235*61046927SAndroid Build Coastguard Worker     ImVec2 ab_dir = b - a;
1236*61046927SAndroid Build Coastguard Worker     float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
1237*61046927SAndroid Build Coastguard Worker     if (dot < 0.0f)
1238*61046927SAndroid Build Coastguard Worker         return a;
1239*61046927SAndroid Build Coastguard Worker     float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
1240*61046927SAndroid Build Coastguard Worker     if (dot > ab_len_sqr)
1241*61046927SAndroid Build Coastguard Worker         return b;
1242*61046927SAndroid Build Coastguard Worker     return a + ab_dir * dot / ab_len_sqr;
1243*61046927SAndroid Build Coastguard Worker }
1244*61046927SAndroid Build Coastguard Worker 
ImTriangleContainsPoint(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & p)1245*61046927SAndroid Build Coastguard Worker bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
1246*61046927SAndroid Build Coastguard Worker {
1247*61046927SAndroid Build Coastguard Worker     bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
1248*61046927SAndroid Build Coastguard Worker     bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
1249*61046927SAndroid Build Coastguard Worker     bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
1250*61046927SAndroid Build Coastguard Worker     return ((b1 == b2) && (b2 == b3));
1251*61046927SAndroid Build Coastguard Worker }
1252*61046927SAndroid Build Coastguard Worker 
ImTriangleBarycentricCoords(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & p,float & out_u,float & out_v,float & out_w)1253*61046927SAndroid Build Coastguard Worker void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
1254*61046927SAndroid Build Coastguard Worker {
1255*61046927SAndroid Build Coastguard Worker     ImVec2 v0 = b - a;
1256*61046927SAndroid Build Coastguard Worker     ImVec2 v1 = c - a;
1257*61046927SAndroid Build Coastguard Worker     ImVec2 v2 = p - a;
1258*61046927SAndroid Build Coastguard Worker     const float denom = v0.x * v1.y - v1.x * v0.y;
1259*61046927SAndroid Build Coastguard Worker     out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
1260*61046927SAndroid Build Coastguard Worker     out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
1261*61046927SAndroid Build Coastguard Worker     out_u = 1.0f - out_v - out_w;
1262*61046927SAndroid Build Coastguard Worker }
1263*61046927SAndroid Build Coastguard Worker 
ImTriangleClosestPoint(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & p)1264*61046927SAndroid Build Coastguard Worker ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
1265*61046927SAndroid Build Coastguard Worker {
1266*61046927SAndroid Build Coastguard Worker     ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
1267*61046927SAndroid Build Coastguard Worker     ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
1268*61046927SAndroid Build Coastguard Worker     ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
1269*61046927SAndroid Build Coastguard Worker     float dist2_ab = ImLengthSqr(p - proj_ab);
1270*61046927SAndroid Build Coastguard Worker     float dist2_bc = ImLengthSqr(p - proj_bc);
1271*61046927SAndroid Build Coastguard Worker     float dist2_ca = ImLengthSqr(p - proj_ca);
1272*61046927SAndroid Build Coastguard Worker     float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
1273*61046927SAndroid Build Coastguard Worker     if (m == dist2_ab)
1274*61046927SAndroid Build Coastguard Worker         return proj_ab;
1275*61046927SAndroid Build Coastguard Worker     if (m == dist2_bc)
1276*61046927SAndroid Build Coastguard Worker         return proj_bc;
1277*61046927SAndroid Build Coastguard Worker     return proj_ca;
1278*61046927SAndroid Build Coastguard Worker }
1279*61046927SAndroid Build Coastguard Worker 
1280*61046927SAndroid Build Coastguard Worker // Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more.
ImStricmp(const char * str1,const char * str2)1281*61046927SAndroid Build Coastguard Worker int ImStricmp(const char* str1, const char* str2)
1282*61046927SAndroid Build Coastguard Worker {
1283*61046927SAndroid Build Coastguard Worker     int d;
1284*61046927SAndroid Build Coastguard Worker     while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
1285*61046927SAndroid Build Coastguard Worker     return d;
1286*61046927SAndroid Build Coastguard Worker }
1287*61046927SAndroid Build Coastguard Worker 
ImStrnicmp(const char * str1,const char * str2,size_t count)1288*61046927SAndroid Build Coastguard Worker int ImStrnicmp(const char* str1, const char* str2, size_t count)
1289*61046927SAndroid Build Coastguard Worker {
1290*61046927SAndroid Build Coastguard Worker     int d = 0;
1291*61046927SAndroid Build Coastguard Worker     while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
1292*61046927SAndroid Build Coastguard Worker     return d;
1293*61046927SAndroid Build Coastguard Worker }
1294*61046927SAndroid Build Coastguard Worker 
ImStrncpy(char * dst,const char * src,size_t count)1295*61046927SAndroid Build Coastguard Worker void ImStrncpy(char* dst, const char* src, size_t count)
1296*61046927SAndroid Build Coastguard Worker {
1297*61046927SAndroid Build Coastguard Worker     if (count < 1)
1298*61046927SAndroid Build Coastguard Worker         return;
1299*61046927SAndroid Build Coastguard Worker     if (count > 1)
1300*61046927SAndroid Build Coastguard Worker         strncpy(dst, src, count - 1);
1301*61046927SAndroid Build Coastguard Worker     dst[count - 1] = 0;
1302*61046927SAndroid Build Coastguard Worker }
1303*61046927SAndroid Build Coastguard Worker 
ImStrdup(const char * str)1304*61046927SAndroid Build Coastguard Worker char* ImStrdup(const char* str)
1305*61046927SAndroid Build Coastguard Worker {
1306*61046927SAndroid Build Coastguard Worker     size_t len = strlen(str);
1307*61046927SAndroid Build Coastguard Worker     void* buf = ImGui::MemAlloc(len + 1);
1308*61046927SAndroid Build Coastguard Worker     return (char*)memcpy(buf, (const void*)str, len + 1);
1309*61046927SAndroid Build Coastguard Worker }
1310*61046927SAndroid Build Coastguard Worker 
ImStrdupcpy(char * dst,size_t * p_dst_size,const char * src)1311*61046927SAndroid Build Coastguard Worker char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
1312*61046927SAndroid Build Coastguard Worker {
1313*61046927SAndroid Build Coastguard Worker     size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
1314*61046927SAndroid Build Coastguard Worker     size_t src_size = strlen(src) + 1;
1315*61046927SAndroid Build Coastguard Worker     if (dst_buf_size < src_size)
1316*61046927SAndroid Build Coastguard Worker     {
1317*61046927SAndroid Build Coastguard Worker         ImGui::MemFree(dst);
1318*61046927SAndroid Build Coastguard Worker         dst = (char*)ImGui::MemAlloc(src_size);
1319*61046927SAndroid Build Coastguard Worker         if (p_dst_size)
1320*61046927SAndroid Build Coastguard Worker             *p_dst_size = src_size;
1321*61046927SAndroid Build Coastguard Worker     }
1322*61046927SAndroid Build Coastguard Worker     return (char*)memcpy(dst, (const void*)src, src_size);
1323*61046927SAndroid Build Coastguard Worker }
1324*61046927SAndroid Build Coastguard Worker 
ImStrchrRange(const char * str,const char * str_end,char c)1325*61046927SAndroid Build Coastguard Worker const char* ImStrchrRange(const char* str, const char* str_end, char c)
1326*61046927SAndroid Build Coastguard Worker {
1327*61046927SAndroid Build Coastguard Worker     const char* p = (const char*)memchr(str, (int)c, str_end - str);
1328*61046927SAndroid Build Coastguard Worker     return p;
1329*61046927SAndroid Build Coastguard Worker }
1330*61046927SAndroid Build Coastguard Worker 
ImStrlenW(const ImWchar * str)1331*61046927SAndroid Build Coastguard Worker int ImStrlenW(const ImWchar* str)
1332*61046927SAndroid Build Coastguard Worker {
1333*61046927SAndroid Build Coastguard Worker     //return (int)wcslen((const wchar_t*)str);	// FIXME-OPT: Could use this when wchar_t are 16-bits
1334*61046927SAndroid Build Coastguard Worker     int n = 0;
1335*61046927SAndroid Build Coastguard Worker     while (*str++) n++;
1336*61046927SAndroid Build Coastguard Worker     return n;
1337*61046927SAndroid Build Coastguard Worker }
1338*61046927SAndroid Build Coastguard Worker 
1339*61046927SAndroid Build Coastguard Worker // Find end-of-line. Return pointer will point to either first \n, either str_end.
ImStreolRange(const char * str,const char * str_end)1340*61046927SAndroid Build Coastguard Worker const char* ImStreolRange(const char* str, const char* str_end)
1341*61046927SAndroid Build Coastguard Worker {
1342*61046927SAndroid Build Coastguard Worker     const char* p = (const char*)memchr(str, '\n', str_end - str);
1343*61046927SAndroid Build Coastguard Worker     return p ? p : str_end;
1344*61046927SAndroid Build Coastguard Worker }
1345*61046927SAndroid Build Coastguard Worker 
ImStrbolW(const ImWchar * buf_mid_line,const ImWchar * buf_begin)1346*61046927SAndroid Build Coastguard Worker const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
1347*61046927SAndroid Build Coastguard Worker {
1348*61046927SAndroid Build Coastguard Worker     while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
1349*61046927SAndroid Build Coastguard Worker         buf_mid_line--;
1350*61046927SAndroid Build Coastguard Worker     return buf_mid_line;
1351*61046927SAndroid Build Coastguard Worker }
1352*61046927SAndroid Build Coastguard Worker 
ImStristr(const char * haystack,const char * haystack_end,const char * needle,const char * needle_end)1353*61046927SAndroid Build Coastguard Worker const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
1354*61046927SAndroid Build Coastguard Worker {
1355*61046927SAndroid Build Coastguard Worker     if (!needle_end)
1356*61046927SAndroid Build Coastguard Worker         needle_end = needle + strlen(needle);
1357*61046927SAndroid Build Coastguard Worker 
1358*61046927SAndroid Build Coastguard Worker     const char un0 = (char)toupper(*needle);
1359*61046927SAndroid Build Coastguard Worker     while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
1360*61046927SAndroid Build Coastguard Worker     {
1361*61046927SAndroid Build Coastguard Worker         if (toupper(*haystack) == un0)
1362*61046927SAndroid Build Coastguard Worker         {
1363*61046927SAndroid Build Coastguard Worker             const char* b = needle + 1;
1364*61046927SAndroid Build Coastguard Worker             for (const char* a = haystack + 1; b < needle_end; a++, b++)
1365*61046927SAndroid Build Coastguard Worker                 if (toupper(*a) != toupper(*b))
1366*61046927SAndroid Build Coastguard Worker                     break;
1367*61046927SAndroid Build Coastguard Worker             if (b == needle_end)
1368*61046927SAndroid Build Coastguard Worker                 return haystack;
1369*61046927SAndroid Build Coastguard Worker         }
1370*61046927SAndroid Build Coastguard Worker         haystack++;
1371*61046927SAndroid Build Coastguard Worker     }
1372*61046927SAndroid Build Coastguard Worker     return NULL;
1373*61046927SAndroid Build Coastguard Worker }
1374*61046927SAndroid Build Coastguard Worker 
1375*61046927SAndroid Build Coastguard Worker // 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.
ImStrTrimBlanks(char * buf)1376*61046927SAndroid Build Coastguard Worker void ImStrTrimBlanks(char* buf)
1377*61046927SAndroid Build Coastguard Worker {
1378*61046927SAndroid Build Coastguard Worker     char* p = buf;
1379*61046927SAndroid Build Coastguard Worker     while (p[0] == ' ' || p[0] == '\t')     // Leading blanks
1380*61046927SAndroid Build Coastguard Worker         p++;
1381*61046927SAndroid Build Coastguard Worker     char* p_start = p;
1382*61046927SAndroid Build Coastguard Worker     while (*p != 0)                         // Find end of string
1383*61046927SAndroid Build Coastguard Worker         p++;
1384*61046927SAndroid Build Coastguard Worker     while (p > p_start && (p[-1] == ' ' || p[-1] == '\t'))  // Trailing blanks
1385*61046927SAndroid Build Coastguard Worker         p--;
1386*61046927SAndroid Build Coastguard Worker     if (p_start != buf)                     // Copy memory if we had leading blanks
1387*61046927SAndroid Build Coastguard Worker         memmove(buf, p_start, p - p_start);
1388*61046927SAndroid Build Coastguard Worker     buf[p - p_start] = 0;                   // Zero terminate
1389*61046927SAndroid Build Coastguard Worker }
1390*61046927SAndroid Build Coastguard Worker 
1391*61046927SAndroid Build Coastguard Worker // A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
1392*61046927SAndroid Build Coastguard Worker // 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.
1393*61046927SAndroid Build Coastguard Worker // B) When buf==NULL vsnprintf() will return the output size.
1394*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
1395*61046927SAndroid Build Coastguard Worker 
1396*61046927SAndroid Build Coastguard Worker //#define IMGUI_USE_STB_SPRINTF
1397*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_USE_STB_SPRINTF
1398*61046927SAndroid Build Coastguard Worker #define STB_SPRINTF_IMPLEMENTATION
1399*61046927SAndroid Build Coastguard Worker #include "imstb_sprintf.h"
1400*61046927SAndroid Build Coastguard Worker #endif
1401*61046927SAndroid Build Coastguard Worker 
1402*61046927SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(vsnprintf)
1403*61046927SAndroid Build Coastguard Worker #define vsnprintf _vsnprintf
1404*61046927SAndroid Build Coastguard Worker #endif
1405*61046927SAndroid Build Coastguard Worker 
ImFormatString(char * buf,size_t buf_size,const char * fmt,...)1406*61046927SAndroid Build Coastguard Worker int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
1407*61046927SAndroid Build Coastguard Worker {
1408*61046927SAndroid Build Coastguard Worker     va_list args;
1409*61046927SAndroid Build Coastguard Worker     va_start(args, fmt);
1410*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_USE_STB_SPRINTF
1411*61046927SAndroid Build Coastguard Worker     int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
1412*61046927SAndroid Build Coastguard Worker #else
1413*61046927SAndroid Build Coastguard Worker     int w = vsnprintf(buf, buf_size, fmt, args);
1414*61046927SAndroid Build Coastguard Worker #endif
1415*61046927SAndroid Build Coastguard Worker     va_end(args);
1416*61046927SAndroid Build Coastguard Worker     if (buf == NULL)
1417*61046927SAndroid Build Coastguard Worker         return w;
1418*61046927SAndroid Build Coastguard Worker     if (w == -1 || w >= (int)buf_size)
1419*61046927SAndroid Build Coastguard Worker         w = (int)buf_size - 1;
1420*61046927SAndroid Build Coastguard Worker     buf[w] = 0;
1421*61046927SAndroid Build Coastguard Worker     return w;
1422*61046927SAndroid Build Coastguard Worker }
1423*61046927SAndroid Build Coastguard Worker 
ImFormatStringV(char * buf,size_t buf_size,const char * fmt,va_list args)1424*61046927SAndroid Build Coastguard Worker int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
1425*61046927SAndroid Build Coastguard Worker {
1426*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_USE_STB_SPRINTF
1427*61046927SAndroid Build Coastguard Worker     int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
1428*61046927SAndroid Build Coastguard Worker #else
1429*61046927SAndroid Build Coastguard Worker     int w = vsnprintf(buf, buf_size, fmt, args);
1430*61046927SAndroid Build Coastguard Worker #endif
1431*61046927SAndroid Build Coastguard Worker     if (buf == NULL)
1432*61046927SAndroid Build Coastguard Worker         return w;
1433*61046927SAndroid Build Coastguard Worker     if (w == -1 || w >= (int)buf_size)
1434*61046927SAndroid Build Coastguard Worker         w = (int)buf_size - 1;
1435*61046927SAndroid Build Coastguard Worker     buf[w] = 0;
1436*61046927SAndroid Build Coastguard Worker     return w;
1437*61046927SAndroid Build Coastguard Worker }
1438*61046927SAndroid Build Coastguard Worker #endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
1439*61046927SAndroid Build Coastguard Worker 
1440*61046927SAndroid Build Coastguard Worker // CRC32 needs a 1KB lookup table (not cache friendly)
1441*61046927SAndroid Build Coastguard Worker // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
1442*61046927SAndroid Build Coastguard Worker // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
1443*61046927SAndroid Build Coastguard Worker static const ImU32 GCrc32LookupTable[256] =
1444*61046927SAndroid Build Coastguard Worker {
1445*61046927SAndroid Build Coastguard Worker     0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
1446*61046927SAndroid Build Coastguard Worker     0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
1447*61046927SAndroid Build Coastguard Worker     0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
1448*61046927SAndroid Build Coastguard Worker     0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
1449*61046927SAndroid Build Coastguard Worker     0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
1450*61046927SAndroid Build Coastguard Worker     0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
1451*61046927SAndroid Build Coastguard Worker     0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
1452*61046927SAndroid Build Coastguard Worker     0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
1453*61046927SAndroid Build Coastguard Worker     0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
1454*61046927SAndroid Build Coastguard Worker     0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
1455*61046927SAndroid Build Coastguard Worker     0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
1456*61046927SAndroid Build Coastguard Worker     0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
1457*61046927SAndroid Build Coastguard Worker     0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
1458*61046927SAndroid Build Coastguard Worker     0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
1459*61046927SAndroid Build Coastguard Worker     0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
1460*61046927SAndroid Build Coastguard Worker     0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
1461*61046927SAndroid Build Coastguard Worker };
1462*61046927SAndroid Build Coastguard Worker 
1463*61046927SAndroid Build Coastguard Worker // Known size hash
1464*61046927SAndroid Build Coastguard Worker // It is ok to call ImHashData on a string with known length but the ### operator won't be supported.
1465*61046927SAndroid Build Coastguard Worker // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
ImHashData(const void * data_p,size_t data_size,ImU32 seed)1466*61046927SAndroid Build Coastguard Worker ImU32 ImHashData(const void* data_p, size_t data_size, ImU32 seed)
1467*61046927SAndroid Build Coastguard Worker {
1468*61046927SAndroid Build Coastguard Worker     ImU32 crc = ~seed;
1469*61046927SAndroid Build Coastguard Worker     const unsigned char* data = (const unsigned char*)data_p;
1470*61046927SAndroid Build Coastguard Worker     const ImU32* crc32_lut = GCrc32LookupTable;
1471*61046927SAndroid Build Coastguard Worker     while (data_size-- != 0)
1472*61046927SAndroid Build Coastguard Worker         crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
1473*61046927SAndroid Build Coastguard Worker     return ~crc;
1474*61046927SAndroid Build Coastguard Worker }
1475*61046927SAndroid Build Coastguard Worker 
1476*61046927SAndroid Build Coastguard Worker // Zero-terminated string hash, with support for ### to reset back to seed value
1477*61046927SAndroid Build Coastguard Worker // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
1478*61046927SAndroid Build Coastguard Worker // Because this syntax is rarely used we are optimizing for the common case.
1479*61046927SAndroid Build Coastguard Worker // - If we reach ### in the string we discard the hash so far and reset to the seed.
1480*61046927SAndroid Build Coastguard Worker // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build)
1481*61046927SAndroid Build Coastguard Worker // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
ImHashStr(const char * data,size_t data_size,ImU32 seed)1482*61046927SAndroid Build Coastguard Worker ImU32 ImHashStr(const char* data, size_t data_size, ImU32 seed)
1483*61046927SAndroid Build Coastguard Worker {
1484*61046927SAndroid Build Coastguard Worker     seed = ~seed;
1485*61046927SAndroid Build Coastguard Worker     ImU32 crc = seed;
1486*61046927SAndroid Build Coastguard Worker     const unsigned char* src = (const unsigned char*)data;
1487*61046927SAndroid Build Coastguard Worker     const ImU32* crc32_lut = GCrc32LookupTable;
1488*61046927SAndroid Build Coastguard Worker     if (data_size != 0)
1489*61046927SAndroid Build Coastguard Worker     {
1490*61046927SAndroid Build Coastguard Worker         while (data_size-- != 0)
1491*61046927SAndroid Build Coastguard Worker         {
1492*61046927SAndroid Build Coastguard Worker             unsigned char c = *src++;
1493*61046927SAndroid Build Coastguard Worker             if (c == '#' && src[0] == '#' && src[1] == '#')
1494*61046927SAndroid Build Coastguard Worker                 crc = seed;
1495*61046927SAndroid Build Coastguard Worker             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
1496*61046927SAndroid Build Coastguard Worker         }
1497*61046927SAndroid Build Coastguard Worker     }
1498*61046927SAndroid Build Coastguard Worker     else
1499*61046927SAndroid Build Coastguard Worker     {
1500*61046927SAndroid Build Coastguard Worker         while (unsigned char c = *src++)
1501*61046927SAndroid Build Coastguard Worker         {
1502*61046927SAndroid Build Coastguard Worker             if (c == '#' && src[0] == '#' && src[1] == '#')
1503*61046927SAndroid Build Coastguard Worker                 crc = seed;
1504*61046927SAndroid Build Coastguard Worker             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
1505*61046927SAndroid Build Coastguard Worker         }
1506*61046927SAndroid Build Coastguard Worker     }
1507*61046927SAndroid Build Coastguard Worker     return ~crc;
1508*61046927SAndroid Build Coastguard Worker }
1509*61046927SAndroid Build Coastguard Worker 
ImFileOpen(const char * filename,const char * mode)1510*61046927SAndroid Build Coastguard Worker FILE* ImFileOpen(const char* filename, const char* mode)
1511*61046927SAndroid Build Coastguard Worker {
1512*61046927SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
1513*61046927SAndroid Build Coastguard Worker     // 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)
1514*61046927SAndroid Build Coastguard Worker     const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
1515*61046927SAndroid Build Coastguard Worker     const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
1516*61046927SAndroid Build Coastguard Worker     ImVector<ImWchar> buf;
1517*61046927SAndroid Build Coastguard Worker     buf.resize(filename_wsize + mode_wsize);
1518*61046927SAndroid Build Coastguard Worker     ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
1519*61046927SAndroid Build Coastguard Worker     ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
1520*61046927SAndroid Build Coastguard Worker     return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
1521*61046927SAndroid Build Coastguard Worker #else
1522*61046927SAndroid Build Coastguard Worker     return fopen(filename, mode);
1523*61046927SAndroid Build Coastguard Worker #endif
1524*61046927SAndroid Build Coastguard Worker }
1525*61046927SAndroid Build Coastguard Worker 
1526*61046927SAndroid Build Coastguard Worker // Load file content into memory
1527*61046927SAndroid Build Coastguard Worker // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
ImFileLoadToMemory(const char * filename,const char * file_open_mode,size_t * out_file_size,int padding_bytes)1528*61046927SAndroid Build Coastguard Worker void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes)
1529*61046927SAndroid Build Coastguard Worker {
1530*61046927SAndroid Build Coastguard Worker     IM_ASSERT(filename && file_open_mode);
1531*61046927SAndroid Build Coastguard Worker     if (out_file_size)
1532*61046927SAndroid Build Coastguard Worker         *out_file_size = 0;
1533*61046927SAndroid Build Coastguard Worker 
1534*61046927SAndroid Build Coastguard Worker     FILE* f;
1535*61046927SAndroid Build Coastguard Worker     if ((f = ImFileOpen(filename, file_open_mode)) == NULL)
1536*61046927SAndroid Build Coastguard Worker         return NULL;
1537*61046927SAndroid Build Coastguard Worker 
1538*61046927SAndroid Build Coastguard Worker     long file_size_signed;
1539*61046927SAndroid Build Coastguard Worker     if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
1540*61046927SAndroid Build Coastguard Worker     {
1541*61046927SAndroid Build Coastguard Worker         fclose(f);
1542*61046927SAndroid Build Coastguard Worker         return NULL;
1543*61046927SAndroid Build Coastguard Worker     }
1544*61046927SAndroid Build Coastguard Worker 
1545*61046927SAndroid Build Coastguard Worker     size_t file_size = (size_t)file_size_signed;
1546*61046927SAndroid Build Coastguard Worker     void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
1547*61046927SAndroid Build Coastguard Worker     if (file_data == NULL)
1548*61046927SAndroid Build Coastguard Worker     {
1549*61046927SAndroid Build Coastguard Worker         fclose(f);
1550*61046927SAndroid Build Coastguard Worker         return NULL;
1551*61046927SAndroid Build Coastguard Worker     }
1552*61046927SAndroid Build Coastguard Worker     if (fread(file_data, 1, file_size, f) != file_size)
1553*61046927SAndroid Build Coastguard Worker     {
1554*61046927SAndroid Build Coastguard Worker         fclose(f);
1555*61046927SAndroid Build Coastguard Worker         ImGui::MemFree(file_data);
1556*61046927SAndroid Build Coastguard Worker         return NULL;
1557*61046927SAndroid Build Coastguard Worker     }
1558*61046927SAndroid Build Coastguard Worker     if (padding_bytes > 0)
1559*61046927SAndroid Build Coastguard Worker         memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
1560*61046927SAndroid Build Coastguard Worker 
1561*61046927SAndroid Build Coastguard Worker     fclose(f);
1562*61046927SAndroid Build Coastguard Worker     if (out_file_size)
1563*61046927SAndroid Build Coastguard Worker         *out_file_size = file_size;
1564*61046927SAndroid Build Coastguard Worker 
1565*61046927SAndroid Build Coastguard Worker     return file_data;
1566*61046927SAndroid Build Coastguard Worker }
1567*61046927SAndroid Build Coastguard Worker 
1568*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1569*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
1570*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1571*61046927SAndroid Build Coastguard Worker 
1572*61046927SAndroid Build Coastguard Worker // Convert UTF-8 to 32-bits character, process single character input.
1573*61046927SAndroid Build Coastguard Worker // Based on stb_from_utf8() from github.com/nothings/stb/
1574*61046927SAndroid Build Coastguard Worker // We handle UTF-8 decoding error by skipping forward.
ImTextCharFromUtf8(unsigned int * out_char,const char * in_text,const char * in_text_end)1575*61046927SAndroid Build Coastguard Worker int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
1576*61046927SAndroid Build Coastguard Worker {
1577*61046927SAndroid Build Coastguard Worker     unsigned int c = (unsigned int)-1;
1578*61046927SAndroid Build Coastguard Worker     const unsigned char* str = (const unsigned char*)in_text;
1579*61046927SAndroid Build Coastguard Worker     if (!(*str & 0x80))
1580*61046927SAndroid Build Coastguard Worker     {
1581*61046927SAndroid Build Coastguard Worker         c = (unsigned int)(*str++);
1582*61046927SAndroid Build Coastguard Worker         *out_char = c;
1583*61046927SAndroid Build Coastguard Worker         return 1;
1584*61046927SAndroid Build Coastguard Worker     }
1585*61046927SAndroid Build Coastguard Worker     if ((*str & 0xe0) == 0xc0)
1586*61046927SAndroid Build Coastguard Worker     {
1587*61046927SAndroid Build Coastguard Worker         *out_char = 0xFFFD; // will be invalid but not end of string
1588*61046927SAndroid Build Coastguard Worker         if (in_text_end && in_text_end - (const char*)str < 2) return 1;
1589*61046927SAndroid Build Coastguard Worker         if (*str < 0xc2) return 2;
1590*61046927SAndroid Build Coastguard Worker         c = (unsigned int)((*str++ & 0x1f) << 6);
1591*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 2;
1592*61046927SAndroid Build Coastguard Worker         c += (*str++ & 0x3f);
1593*61046927SAndroid Build Coastguard Worker         *out_char = c;
1594*61046927SAndroid Build Coastguard Worker         return 2;
1595*61046927SAndroid Build Coastguard Worker     }
1596*61046927SAndroid Build Coastguard Worker     if ((*str & 0xf0) == 0xe0)
1597*61046927SAndroid Build Coastguard Worker     {
1598*61046927SAndroid Build Coastguard Worker         *out_char = 0xFFFD; // will be invalid but not end of string
1599*61046927SAndroid Build Coastguard Worker         if (in_text_end && in_text_end - (const char*)str < 3) return 1;
1600*61046927SAndroid Build Coastguard Worker         if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
1601*61046927SAndroid Build Coastguard Worker         if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
1602*61046927SAndroid Build Coastguard Worker         c = (unsigned int)((*str++ & 0x0f) << 12);
1603*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 3;
1604*61046927SAndroid Build Coastguard Worker         c += (unsigned int)((*str++ & 0x3f) << 6);
1605*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 3;
1606*61046927SAndroid Build Coastguard Worker         c += (*str++ & 0x3f);
1607*61046927SAndroid Build Coastguard Worker         *out_char = c;
1608*61046927SAndroid Build Coastguard Worker         return 3;
1609*61046927SAndroid Build Coastguard Worker     }
1610*61046927SAndroid Build Coastguard Worker     if ((*str & 0xf8) == 0xf0)
1611*61046927SAndroid Build Coastguard Worker     {
1612*61046927SAndroid Build Coastguard Worker         *out_char = 0xFFFD; // will be invalid but not end of string
1613*61046927SAndroid Build Coastguard Worker         if (in_text_end && in_text_end - (const char*)str < 4) return 1;
1614*61046927SAndroid Build Coastguard Worker         if (*str > 0xf4) return 4;
1615*61046927SAndroid Build Coastguard Worker         if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
1616*61046927SAndroid Build Coastguard Worker         if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
1617*61046927SAndroid Build Coastguard Worker         c = (unsigned int)((*str++ & 0x07) << 18);
1618*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 4;
1619*61046927SAndroid Build Coastguard Worker         c += (unsigned int)((*str++ & 0x3f) << 12);
1620*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 4;
1621*61046927SAndroid Build Coastguard Worker         c += (unsigned int)((*str++ & 0x3f) << 6);
1622*61046927SAndroid Build Coastguard Worker         if ((*str & 0xc0) != 0x80) return 4;
1623*61046927SAndroid Build Coastguard Worker         c += (*str++ & 0x3f);
1624*61046927SAndroid Build Coastguard Worker         // utf-8 encodings of values used in surrogate pairs are invalid
1625*61046927SAndroid Build Coastguard Worker         if ((c & 0xFFFFF800) == 0xD800) return 4;
1626*61046927SAndroid Build Coastguard Worker         *out_char = c;
1627*61046927SAndroid Build Coastguard Worker         return 4;
1628*61046927SAndroid Build Coastguard Worker     }
1629*61046927SAndroid Build Coastguard Worker     *out_char = 0;
1630*61046927SAndroid Build Coastguard Worker     return 0;
1631*61046927SAndroid Build Coastguard Worker }
1632*61046927SAndroid Build Coastguard Worker 
ImTextStrFromUtf8(ImWchar * buf,int buf_size,const char * in_text,const char * in_text_end,const char ** in_text_remaining)1633*61046927SAndroid Build Coastguard Worker int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
1634*61046927SAndroid Build Coastguard Worker {
1635*61046927SAndroid Build Coastguard Worker     ImWchar* buf_out = buf;
1636*61046927SAndroid Build Coastguard Worker     ImWchar* buf_end = buf + buf_size;
1637*61046927SAndroid Build Coastguard Worker     while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
1638*61046927SAndroid Build Coastguard Worker     {
1639*61046927SAndroid Build Coastguard Worker         unsigned int c;
1640*61046927SAndroid Build Coastguard Worker         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
1641*61046927SAndroid Build Coastguard Worker         if (c == 0)
1642*61046927SAndroid Build Coastguard Worker             break;
1643*61046927SAndroid Build Coastguard Worker         if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes
1644*61046927SAndroid Build Coastguard Worker             *buf_out++ = (ImWchar)c;
1645*61046927SAndroid Build Coastguard Worker     }
1646*61046927SAndroid Build Coastguard Worker     *buf_out = 0;
1647*61046927SAndroid Build Coastguard Worker     if (in_text_remaining)
1648*61046927SAndroid Build Coastguard Worker         *in_text_remaining = in_text;
1649*61046927SAndroid Build Coastguard Worker     return (int)(buf_out - buf);
1650*61046927SAndroid Build Coastguard Worker }
1651*61046927SAndroid Build Coastguard Worker 
ImTextCountCharsFromUtf8(const char * in_text,const char * in_text_end)1652*61046927SAndroid Build Coastguard Worker int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
1653*61046927SAndroid Build Coastguard Worker {
1654*61046927SAndroid Build Coastguard Worker     int char_count = 0;
1655*61046927SAndroid Build Coastguard Worker     while ((!in_text_end || in_text < in_text_end) && *in_text)
1656*61046927SAndroid Build Coastguard Worker     {
1657*61046927SAndroid Build Coastguard Worker         unsigned int c;
1658*61046927SAndroid Build Coastguard Worker         in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
1659*61046927SAndroid Build Coastguard Worker         if (c == 0)
1660*61046927SAndroid Build Coastguard Worker             break;
1661*61046927SAndroid Build Coastguard Worker         if (c < 0x10000)
1662*61046927SAndroid Build Coastguard Worker             char_count++;
1663*61046927SAndroid Build Coastguard Worker     }
1664*61046927SAndroid Build Coastguard Worker     return char_count;
1665*61046927SAndroid Build Coastguard Worker }
1666*61046927SAndroid Build Coastguard Worker 
1667*61046927SAndroid Build Coastguard Worker // Based on stb_to_utf8() from github.com/nothings/stb/
ImTextCharToUtf8(char * buf,int buf_size,unsigned int c)1668*61046927SAndroid Build Coastguard Worker static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
1669*61046927SAndroid Build Coastguard Worker {
1670*61046927SAndroid Build Coastguard Worker     if (c < 0x80)
1671*61046927SAndroid Build Coastguard Worker     {
1672*61046927SAndroid Build Coastguard Worker         buf[0] = (char)c;
1673*61046927SAndroid Build Coastguard Worker         return 1;
1674*61046927SAndroid Build Coastguard Worker     }
1675*61046927SAndroid Build Coastguard Worker     if (c < 0x800)
1676*61046927SAndroid Build Coastguard Worker     {
1677*61046927SAndroid Build Coastguard Worker         if (buf_size < 2) return 0;
1678*61046927SAndroid Build Coastguard Worker         buf[0] = (char)(0xc0 + (c >> 6));
1679*61046927SAndroid Build Coastguard Worker         buf[1] = (char)(0x80 + (c & 0x3f));
1680*61046927SAndroid Build Coastguard Worker         return 2;
1681*61046927SAndroid Build Coastguard Worker     }
1682*61046927SAndroid Build Coastguard Worker     if (c >= 0xdc00 && c < 0xe000)
1683*61046927SAndroid Build Coastguard Worker     {
1684*61046927SAndroid Build Coastguard Worker         return 0;
1685*61046927SAndroid Build Coastguard Worker     }
1686*61046927SAndroid Build Coastguard Worker     if (c >= 0xd800 && c < 0xdc00)
1687*61046927SAndroid Build Coastguard Worker     {
1688*61046927SAndroid Build Coastguard Worker         if (buf_size < 4) return 0;
1689*61046927SAndroid Build Coastguard Worker         buf[0] = (char)(0xf0 + (c >> 18));
1690*61046927SAndroid Build Coastguard Worker         buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
1691*61046927SAndroid Build Coastguard Worker         buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
1692*61046927SAndroid Build Coastguard Worker         buf[3] = (char)(0x80 + ((c ) & 0x3f));
1693*61046927SAndroid Build Coastguard Worker         return 4;
1694*61046927SAndroid Build Coastguard Worker     }
1695*61046927SAndroid Build Coastguard Worker     //else if (c < 0x10000)
1696*61046927SAndroid Build Coastguard Worker     {
1697*61046927SAndroid Build Coastguard Worker         if (buf_size < 3) return 0;
1698*61046927SAndroid Build Coastguard Worker         buf[0] = (char)(0xe0 + (c >> 12));
1699*61046927SAndroid Build Coastguard Worker         buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
1700*61046927SAndroid Build Coastguard Worker         buf[2] = (char)(0x80 + ((c ) & 0x3f));
1701*61046927SAndroid Build Coastguard Worker         return 3;
1702*61046927SAndroid Build Coastguard Worker     }
1703*61046927SAndroid Build Coastguard Worker }
1704*61046927SAndroid Build Coastguard Worker 
1705*61046927SAndroid Build Coastguard Worker // Not optimal but we very rarely use this function.
ImTextCountUtf8BytesFromChar(const char * in_text,const char * in_text_end)1706*61046927SAndroid Build Coastguard Worker int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
1707*61046927SAndroid Build Coastguard Worker {
1708*61046927SAndroid Build Coastguard Worker     unsigned int dummy = 0;
1709*61046927SAndroid Build Coastguard Worker     return ImTextCharFromUtf8(&dummy, in_text, in_text_end);
1710*61046927SAndroid Build Coastguard Worker }
1711*61046927SAndroid Build Coastguard Worker 
ImTextCountUtf8BytesFromChar(unsigned int c)1712*61046927SAndroid Build Coastguard Worker static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
1713*61046927SAndroid Build Coastguard Worker {
1714*61046927SAndroid Build Coastguard Worker     if (c < 0x80) return 1;
1715*61046927SAndroid Build Coastguard Worker     if (c < 0x800) return 2;
1716*61046927SAndroid Build Coastguard Worker     if (c >= 0xdc00 && c < 0xe000) return 0;
1717*61046927SAndroid Build Coastguard Worker     if (c >= 0xd800 && c < 0xdc00) return 4;
1718*61046927SAndroid Build Coastguard Worker     return 3;
1719*61046927SAndroid Build Coastguard Worker }
1720*61046927SAndroid Build Coastguard Worker 
ImTextStrToUtf8(char * buf,int buf_size,const ImWchar * in_text,const ImWchar * in_text_end)1721*61046927SAndroid Build Coastguard Worker int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
1722*61046927SAndroid Build Coastguard Worker {
1723*61046927SAndroid Build Coastguard Worker     char* buf_out = buf;
1724*61046927SAndroid Build Coastguard Worker     const char* buf_end = buf + buf_size;
1725*61046927SAndroid Build Coastguard Worker     while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
1726*61046927SAndroid Build Coastguard Worker     {
1727*61046927SAndroid Build Coastguard Worker         unsigned int c = (unsigned int)(*in_text++);
1728*61046927SAndroid Build Coastguard Worker         if (c < 0x80)
1729*61046927SAndroid Build Coastguard Worker             *buf_out++ = (char)c;
1730*61046927SAndroid Build Coastguard Worker         else
1731*61046927SAndroid Build Coastguard Worker             buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);
1732*61046927SAndroid Build Coastguard Worker     }
1733*61046927SAndroid Build Coastguard Worker     *buf_out = 0;
1734*61046927SAndroid Build Coastguard Worker     return (int)(buf_out - buf);
1735*61046927SAndroid Build Coastguard Worker }
1736*61046927SAndroid Build Coastguard Worker 
ImTextCountUtf8BytesFromStr(const ImWchar * in_text,const ImWchar * in_text_end)1737*61046927SAndroid Build Coastguard Worker int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
1738*61046927SAndroid Build Coastguard Worker {
1739*61046927SAndroid Build Coastguard Worker     int bytes_count = 0;
1740*61046927SAndroid Build Coastguard Worker     while ((!in_text_end || in_text < in_text_end) && *in_text)
1741*61046927SAndroid Build Coastguard Worker     {
1742*61046927SAndroid Build Coastguard Worker         unsigned int c = (unsigned int)(*in_text++);
1743*61046927SAndroid Build Coastguard Worker         if (c < 0x80)
1744*61046927SAndroid Build Coastguard Worker             bytes_count++;
1745*61046927SAndroid Build Coastguard Worker         else
1746*61046927SAndroid Build Coastguard Worker             bytes_count += ImTextCountUtf8BytesFromChar(c);
1747*61046927SAndroid Build Coastguard Worker     }
1748*61046927SAndroid Build Coastguard Worker     return bytes_count;
1749*61046927SAndroid Build Coastguard Worker }
1750*61046927SAndroid Build Coastguard Worker 
1751*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1752*61046927SAndroid Build Coastguard Worker // [SECTION] MISC HELPER/UTILTIES (Color functions)
1753*61046927SAndroid Build Coastguard Worker // Note: The Convert functions are early design which are not consistent with other API.
1754*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1755*61046927SAndroid Build Coastguard Worker 
ColorConvertU32ToFloat4(ImU32 in)1756*61046927SAndroid Build Coastguard Worker ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
1757*61046927SAndroid Build Coastguard Worker {
1758*61046927SAndroid Build Coastguard Worker     float s = 1.0f/255.0f;
1759*61046927SAndroid Build Coastguard Worker     return ImVec4(
1760*61046927SAndroid Build Coastguard Worker         ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
1761*61046927SAndroid Build Coastguard Worker         ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
1762*61046927SAndroid Build Coastguard Worker         ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
1763*61046927SAndroid Build Coastguard Worker         ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
1764*61046927SAndroid Build Coastguard Worker }
1765*61046927SAndroid Build Coastguard Worker 
ColorConvertFloat4ToU32(const ImVec4 & in)1766*61046927SAndroid Build Coastguard Worker ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
1767*61046927SAndroid Build Coastguard Worker {
1768*61046927SAndroid Build Coastguard Worker     ImU32 out;
1769*61046927SAndroid Build Coastguard Worker     out  = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
1770*61046927SAndroid Build Coastguard Worker     out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
1771*61046927SAndroid Build Coastguard Worker     out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
1772*61046927SAndroid Build Coastguard Worker     out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
1773*61046927SAndroid Build Coastguard Worker     return out;
1774*61046927SAndroid Build Coastguard Worker }
1775*61046927SAndroid Build Coastguard Worker 
1776*61046927SAndroid Build Coastguard Worker // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
1777*61046927SAndroid Build Coastguard Worker // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
ColorConvertRGBtoHSV(float r,float g,float b,float & out_h,float & out_s,float & out_v)1778*61046927SAndroid Build Coastguard Worker void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
1779*61046927SAndroid Build Coastguard Worker {
1780*61046927SAndroid Build Coastguard Worker     float K = 0.f;
1781*61046927SAndroid Build Coastguard Worker     if (g < b)
1782*61046927SAndroid Build Coastguard Worker     {
1783*61046927SAndroid Build Coastguard Worker         ImSwap(g, b);
1784*61046927SAndroid Build Coastguard Worker         K = -1.f;
1785*61046927SAndroid Build Coastguard Worker     }
1786*61046927SAndroid Build Coastguard Worker     if (r < g)
1787*61046927SAndroid Build Coastguard Worker     {
1788*61046927SAndroid Build Coastguard Worker         ImSwap(r, g);
1789*61046927SAndroid Build Coastguard Worker         K = -2.f / 6.f - K;
1790*61046927SAndroid Build Coastguard Worker     }
1791*61046927SAndroid Build Coastguard Worker 
1792*61046927SAndroid Build Coastguard Worker     const float chroma = r - (g < b ? g : b);
1793*61046927SAndroid Build Coastguard Worker     out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
1794*61046927SAndroid Build Coastguard Worker     out_s = chroma / (r + 1e-20f);
1795*61046927SAndroid Build Coastguard Worker     out_v = r;
1796*61046927SAndroid Build Coastguard Worker }
1797*61046927SAndroid Build Coastguard Worker 
1798*61046927SAndroid Build Coastguard Worker // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
1799*61046927SAndroid Build Coastguard Worker // also http://en.wikipedia.org/wiki/HSL_and_HSV
ColorConvertHSVtoRGB(float h,float s,float v,float & out_r,float & out_g,float & out_b)1800*61046927SAndroid Build Coastguard Worker void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
1801*61046927SAndroid Build Coastguard Worker {
1802*61046927SAndroid Build Coastguard Worker     if (s == 0.0f)
1803*61046927SAndroid Build Coastguard Worker     {
1804*61046927SAndroid Build Coastguard Worker         // gray
1805*61046927SAndroid Build Coastguard Worker         out_r = out_g = out_b = v;
1806*61046927SAndroid Build Coastguard Worker         return;
1807*61046927SAndroid Build Coastguard Worker     }
1808*61046927SAndroid Build Coastguard Worker 
1809*61046927SAndroid Build Coastguard Worker     h = ImFmod(h, 1.0f) / (60.0f/360.0f);
1810*61046927SAndroid Build Coastguard Worker     int   i = (int)h;
1811*61046927SAndroid Build Coastguard Worker     float f = h - (float)i;
1812*61046927SAndroid Build Coastguard Worker     float p = v * (1.0f - s);
1813*61046927SAndroid Build Coastguard Worker     float q = v * (1.0f - s * f);
1814*61046927SAndroid Build Coastguard Worker     float t = v * (1.0f - s * (1.0f - f));
1815*61046927SAndroid Build Coastguard Worker 
1816*61046927SAndroid Build Coastguard Worker     switch (i)
1817*61046927SAndroid Build Coastguard Worker     {
1818*61046927SAndroid Build Coastguard Worker     case 0: out_r = v; out_g = t; out_b = p; break;
1819*61046927SAndroid Build Coastguard Worker     case 1: out_r = q; out_g = v; out_b = p; break;
1820*61046927SAndroid Build Coastguard Worker     case 2: out_r = p; out_g = v; out_b = t; break;
1821*61046927SAndroid Build Coastguard Worker     case 3: out_r = p; out_g = q; out_b = v; break;
1822*61046927SAndroid Build Coastguard Worker     case 4: out_r = t; out_g = p; out_b = v; break;
1823*61046927SAndroid Build Coastguard Worker     case 5: default: out_r = v; out_g = p; out_b = q; break;
1824*61046927SAndroid Build Coastguard Worker     }
1825*61046927SAndroid Build Coastguard Worker }
1826*61046927SAndroid Build Coastguard Worker 
GetColorU32(ImGuiCol idx,float alpha_mul)1827*61046927SAndroid Build Coastguard Worker ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
1828*61046927SAndroid Build Coastguard Worker {
1829*61046927SAndroid Build Coastguard Worker     ImGuiStyle& style = GImGui->Style;
1830*61046927SAndroid Build Coastguard Worker     ImVec4 c = style.Colors[idx];
1831*61046927SAndroid Build Coastguard Worker     c.w *= style.Alpha * alpha_mul;
1832*61046927SAndroid Build Coastguard Worker     return ColorConvertFloat4ToU32(c);
1833*61046927SAndroid Build Coastguard Worker }
1834*61046927SAndroid Build Coastguard Worker 
GetColorU32(const ImVec4 & col)1835*61046927SAndroid Build Coastguard Worker ImU32 ImGui::GetColorU32(const ImVec4& col)
1836*61046927SAndroid Build Coastguard Worker {
1837*61046927SAndroid Build Coastguard Worker     ImGuiStyle& style = GImGui->Style;
1838*61046927SAndroid Build Coastguard Worker     ImVec4 c = col;
1839*61046927SAndroid Build Coastguard Worker     c.w *= style.Alpha;
1840*61046927SAndroid Build Coastguard Worker     return ColorConvertFloat4ToU32(c);
1841*61046927SAndroid Build Coastguard Worker }
1842*61046927SAndroid Build Coastguard Worker 
GetStyleColorVec4(ImGuiCol idx)1843*61046927SAndroid Build Coastguard Worker const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
1844*61046927SAndroid Build Coastguard Worker {
1845*61046927SAndroid Build Coastguard Worker     ImGuiStyle& style = GImGui->Style;
1846*61046927SAndroid Build Coastguard Worker     return style.Colors[idx];
1847*61046927SAndroid Build Coastguard Worker }
1848*61046927SAndroid Build Coastguard Worker 
GetColorU32(ImU32 col)1849*61046927SAndroid Build Coastguard Worker ImU32 ImGui::GetColorU32(ImU32 col)
1850*61046927SAndroid Build Coastguard Worker {
1851*61046927SAndroid Build Coastguard Worker     float style_alpha = GImGui->Style.Alpha;
1852*61046927SAndroid Build Coastguard Worker     if (style_alpha >= 1.0f)
1853*61046927SAndroid Build Coastguard Worker         return col;
1854*61046927SAndroid Build Coastguard Worker     ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
1855*61046927SAndroid Build Coastguard Worker     a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
1856*61046927SAndroid Build Coastguard Worker     return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
1857*61046927SAndroid Build Coastguard Worker }
1858*61046927SAndroid Build Coastguard Worker 
1859*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1860*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiStorage
1861*61046927SAndroid Build Coastguard Worker // Helper: Key->value storage
1862*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
1863*61046927SAndroid Build Coastguard Worker 
1864*61046927SAndroid Build Coastguard Worker // std::lower_bound but without the bullshit
LowerBound(ImVector<ImGuiStorage::Pair> & data,ImGuiID key)1865*61046927SAndroid Build Coastguard Worker static ImGuiStorage::Pair* LowerBound(ImVector<ImGuiStorage::Pair>& data, ImGuiID key)
1866*61046927SAndroid Build Coastguard Worker {
1867*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* first = data.Data;
1868*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* last = data.Data + data.Size;
1869*61046927SAndroid Build Coastguard Worker     size_t count = (size_t)(last - first);
1870*61046927SAndroid Build Coastguard Worker     while (count > 0)
1871*61046927SAndroid Build Coastguard Worker     {
1872*61046927SAndroid Build Coastguard Worker         size_t count2 = count >> 1;
1873*61046927SAndroid Build Coastguard Worker         ImGuiStorage::Pair* mid = first + count2;
1874*61046927SAndroid Build Coastguard Worker         if (mid->key < key)
1875*61046927SAndroid Build Coastguard Worker         {
1876*61046927SAndroid Build Coastguard Worker             first = ++mid;
1877*61046927SAndroid Build Coastguard Worker             count -= count2 + 1;
1878*61046927SAndroid Build Coastguard Worker         }
1879*61046927SAndroid Build Coastguard Worker         else
1880*61046927SAndroid Build Coastguard Worker         {
1881*61046927SAndroid Build Coastguard Worker             count = count2;
1882*61046927SAndroid Build Coastguard Worker         }
1883*61046927SAndroid Build Coastguard Worker     }
1884*61046927SAndroid Build Coastguard Worker     return first;
1885*61046927SAndroid Build Coastguard Worker }
1886*61046927SAndroid Build Coastguard Worker 
1887*61046927SAndroid Build Coastguard Worker // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
BuildSortByKey()1888*61046927SAndroid Build Coastguard Worker void ImGuiStorage::BuildSortByKey()
1889*61046927SAndroid Build Coastguard Worker {
1890*61046927SAndroid Build Coastguard Worker     struct StaticFunc
1891*61046927SAndroid Build Coastguard Worker     {
1892*61046927SAndroid Build Coastguard Worker         static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
1893*61046927SAndroid Build Coastguard Worker         {
1894*61046927SAndroid Build Coastguard Worker             // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
1895*61046927SAndroid Build Coastguard Worker             if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1;
1896*61046927SAndroid Build Coastguard Worker             if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1;
1897*61046927SAndroid Build Coastguard Worker             return 0;
1898*61046927SAndroid Build Coastguard Worker         }
1899*61046927SAndroid Build Coastguard Worker     };
1900*61046927SAndroid Build Coastguard Worker     if (Data.Size > 1)
1901*61046927SAndroid Build Coastguard Worker         ImQsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID);
1902*61046927SAndroid Build Coastguard Worker }
1903*61046927SAndroid Build Coastguard Worker 
GetInt(ImGuiID key,int default_val) const1904*61046927SAndroid Build Coastguard Worker int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
1905*61046927SAndroid Build Coastguard Worker {
1906*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1907*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1908*61046927SAndroid Build Coastguard Worker         return default_val;
1909*61046927SAndroid Build Coastguard Worker     return it->val_i;
1910*61046927SAndroid Build Coastguard Worker }
1911*61046927SAndroid Build Coastguard Worker 
GetBool(ImGuiID key,bool default_val) const1912*61046927SAndroid Build Coastguard Worker bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
1913*61046927SAndroid Build Coastguard Worker {
1914*61046927SAndroid Build Coastguard Worker     return GetInt(key, default_val ? 1 : 0) != 0;
1915*61046927SAndroid Build Coastguard Worker }
1916*61046927SAndroid Build Coastguard Worker 
GetFloat(ImGuiID key,float default_val) const1917*61046927SAndroid Build Coastguard Worker float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
1918*61046927SAndroid Build Coastguard Worker {
1919*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1920*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1921*61046927SAndroid Build Coastguard Worker         return default_val;
1922*61046927SAndroid Build Coastguard Worker     return it->val_f;
1923*61046927SAndroid Build Coastguard Worker }
1924*61046927SAndroid Build Coastguard Worker 
GetVoidPtr(ImGuiID key) const1925*61046927SAndroid Build Coastguard Worker void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
1926*61046927SAndroid Build Coastguard Worker {
1927*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
1928*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1929*61046927SAndroid Build Coastguard Worker         return NULL;
1930*61046927SAndroid Build Coastguard Worker     return it->val_p;
1931*61046927SAndroid Build Coastguard Worker }
1932*61046927SAndroid Build Coastguard Worker 
1933*61046927SAndroid Build Coastguard Worker // 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.
GetIntRef(ImGuiID key,int default_val)1934*61046927SAndroid Build Coastguard Worker int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
1935*61046927SAndroid Build Coastguard Worker {
1936*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1937*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1938*61046927SAndroid Build Coastguard Worker         it = Data.insert(it, Pair(key, default_val));
1939*61046927SAndroid Build Coastguard Worker     return &it->val_i;
1940*61046927SAndroid Build Coastguard Worker }
1941*61046927SAndroid Build Coastguard Worker 
GetBoolRef(ImGuiID key,bool default_val)1942*61046927SAndroid Build Coastguard Worker bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
1943*61046927SAndroid Build Coastguard Worker {
1944*61046927SAndroid Build Coastguard Worker     return (bool*)GetIntRef(key, default_val ? 1 : 0);
1945*61046927SAndroid Build Coastguard Worker }
1946*61046927SAndroid Build Coastguard Worker 
GetFloatRef(ImGuiID key,float default_val)1947*61046927SAndroid Build Coastguard Worker float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
1948*61046927SAndroid Build Coastguard Worker {
1949*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1950*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1951*61046927SAndroid Build Coastguard Worker         it = Data.insert(it, Pair(key, default_val));
1952*61046927SAndroid Build Coastguard Worker     return &it->val_f;
1953*61046927SAndroid Build Coastguard Worker }
1954*61046927SAndroid Build Coastguard Worker 
GetVoidPtrRef(ImGuiID key,void * default_val)1955*61046927SAndroid Build Coastguard Worker void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
1956*61046927SAndroid Build Coastguard Worker {
1957*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1958*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1959*61046927SAndroid Build Coastguard Worker         it = Data.insert(it, Pair(key, default_val));
1960*61046927SAndroid Build Coastguard Worker     return &it->val_p;
1961*61046927SAndroid Build Coastguard Worker }
1962*61046927SAndroid Build Coastguard Worker 
1963*61046927SAndroid Build Coastguard Worker // 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)
SetInt(ImGuiID key,int val)1964*61046927SAndroid Build Coastguard Worker void ImGuiStorage::SetInt(ImGuiID key, int val)
1965*61046927SAndroid Build Coastguard Worker {
1966*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1967*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1968*61046927SAndroid Build Coastguard Worker     {
1969*61046927SAndroid Build Coastguard Worker         Data.insert(it, Pair(key, val));
1970*61046927SAndroid Build Coastguard Worker         return;
1971*61046927SAndroid Build Coastguard Worker     }
1972*61046927SAndroid Build Coastguard Worker     it->val_i = val;
1973*61046927SAndroid Build Coastguard Worker }
1974*61046927SAndroid Build Coastguard Worker 
SetBool(ImGuiID key,bool val)1975*61046927SAndroid Build Coastguard Worker void ImGuiStorage::SetBool(ImGuiID key, bool val)
1976*61046927SAndroid Build Coastguard Worker {
1977*61046927SAndroid Build Coastguard Worker     SetInt(key, val ? 1 : 0);
1978*61046927SAndroid Build Coastguard Worker }
1979*61046927SAndroid Build Coastguard Worker 
SetFloat(ImGuiID key,float val)1980*61046927SAndroid Build Coastguard Worker void ImGuiStorage::SetFloat(ImGuiID key, float val)
1981*61046927SAndroid Build Coastguard Worker {
1982*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1983*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1984*61046927SAndroid Build Coastguard Worker     {
1985*61046927SAndroid Build Coastguard Worker         Data.insert(it, Pair(key, val));
1986*61046927SAndroid Build Coastguard Worker         return;
1987*61046927SAndroid Build Coastguard Worker     }
1988*61046927SAndroid Build Coastguard Worker     it->val_f = val;
1989*61046927SAndroid Build Coastguard Worker }
1990*61046927SAndroid Build Coastguard Worker 
SetVoidPtr(ImGuiID key,void * val)1991*61046927SAndroid Build Coastguard Worker void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
1992*61046927SAndroid Build Coastguard Worker {
1993*61046927SAndroid Build Coastguard Worker     ImGuiStorage::Pair* it = LowerBound(Data, key);
1994*61046927SAndroid Build Coastguard Worker     if (it == Data.end() || it->key != key)
1995*61046927SAndroid Build Coastguard Worker     {
1996*61046927SAndroid Build Coastguard Worker         Data.insert(it, Pair(key, val));
1997*61046927SAndroid Build Coastguard Worker         return;
1998*61046927SAndroid Build Coastguard Worker     }
1999*61046927SAndroid Build Coastguard Worker     it->val_p = val;
2000*61046927SAndroid Build Coastguard Worker }
2001*61046927SAndroid Build Coastguard Worker 
SetAllInt(int v)2002*61046927SAndroid Build Coastguard Worker void ImGuiStorage::SetAllInt(int v)
2003*61046927SAndroid Build Coastguard Worker {
2004*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < Data.Size; i++)
2005*61046927SAndroid Build Coastguard Worker         Data[i].val_i = v;
2006*61046927SAndroid Build Coastguard Worker }
2007*61046927SAndroid Build Coastguard Worker 
2008*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2009*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiTextFilter
2010*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2011*61046927SAndroid Build Coastguard Worker 
2012*61046927SAndroid Build Coastguard Worker // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
ImGuiTextFilter(const char * default_filter)2013*61046927SAndroid Build Coastguard Worker ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
2014*61046927SAndroid Build Coastguard Worker {
2015*61046927SAndroid Build Coastguard Worker     if (default_filter)
2016*61046927SAndroid Build Coastguard Worker     {
2017*61046927SAndroid Build Coastguard Worker         ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
2018*61046927SAndroid Build Coastguard Worker         Build();
2019*61046927SAndroid Build Coastguard Worker     }
2020*61046927SAndroid Build Coastguard Worker     else
2021*61046927SAndroid Build Coastguard Worker     {
2022*61046927SAndroid Build Coastguard Worker         InputBuf[0] = 0;
2023*61046927SAndroid Build Coastguard Worker         CountGrep = 0;
2024*61046927SAndroid Build Coastguard Worker     }
2025*61046927SAndroid Build Coastguard Worker }
2026*61046927SAndroid Build Coastguard Worker 
Draw(const char * label,float width)2027*61046927SAndroid Build Coastguard Worker bool ImGuiTextFilter::Draw(const char* label, float width)
2028*61046927SAndroid Build Coastguard Worker {
2029*61046927SAndroid Build Coastguard Worker     if (width != 0.0f)
2030*61046927SAndroid Build Coastguard Worker         ImGui::PushItemWidth(width);
2031*61046927SAndroid Build Coastguard Worker     bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
2032*61046927SAndroid Build Coastguard Worker     if (width != 0.0f)
2033*61046927SAndroid Build Coastguard Worker         ImGui::PopItemWidth();
2034*61046927SAndroid Build Coastguard Worker     if (value_changed)
2035*61046927SAndroid Build Coastguard Worker         Build();
2036*61046927SAndroid Build Coastguard Worker     return value_changed;
2037*61046927SAndroid Build Coastguard Worker }
2038*61046927SAndroid Build Coastguard Worker 
split(char separator,ImVector<TextRange> * out) const2039*61046927SAndroid Build Coastguard Worker void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>* out) const
2040*61046927SAndroid Build Coastguard Worker {
2041*61046927SAndroid Build Coastguard Worker     out->resize(0);
2042*61046927SAndroid Build Coastguard Worker     const char* wb = b;
2043*61046927SAndroid Build Coastguard Worker     const char* we = wb;
2044*61046927SAndroid Build Coastguard Worker     while (we < e)
2045*61046927SAndroid Build Coastguard Worker     {
2046*61046927SAndroid Build Coastguard Worker         if (*we == separator)
2047*61046927SAndroid Build Coastguard Worker         {
2048*61046927SAndroid Build Coastguard Worker             out->push_back(TextRange(wb, we));
2049*61046927SAndroid Build Coastguard Worker             wb = we + 1;
2050*61046927SAndroid Build Coastguard Worker         }
2051*61046927SAndroid Build Coastguard Worker         we++;
2052*61046927SAndroid Build Coastguard Worker     }
2053*61046927SAndroid Build Coastguard Worker     if (wb != we)
2054*61046927SAndroid Build Coastguard Worker         out->push_back(TextRange(wb, we));
2055*61046927SAndroid Build Coastguard Worker }
2056*61046927SAndroid Build Coastguard Worker 
Build()2057*61046927SAndroid Build Coastguard Worker void ImGuiTextFilter::Build()
2058*61046927SAndroid Build Coastguard Worker {
2059*61046927SAndroid Build Coastguard Worker     Filters.resize(0);
2060*61046927SAndroid Build Coastguard Worker     TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
2061*61046927SAndroid Build Coastguard Worker     input_range.split(',', &Filters);
2062*61046927SAndroid Build Coastguard Worker 
2063*61046927SAndroid Build Coastguard Worker     CountGrep = 0;
2064*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != Filters.Size; i++)
2065*61046927SAndroid Build Coastguard Worker     {
2066*61046927SAndroid Build Coastguard Worker         TextRange& f = Filters[i];
2067*61046927SAndroid Build Coastguard Worker         while (f.b < f.e && ImCharIsBlankA(f.b[0]))
2068*61046927SAndroid Build Coastguard Worker             f.b++;
2069*61046927SAndroid Build Coastguard Worker         while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
2070*61046927SAndroid Build Coastguard Worker             f.e--;
2071*61046927SAndroid Build Coastguard Worker         if (f.empty())
2072*61046927SAndroid Build Coastguard Worker             continue;
2073*61046927SAndroid Build Coastguard Worker         if (Filters[i].b[0] != '-')
2074*61046927SAndroid Build Coastguard Worker             CountGrep += 1;
2075*61046927SAndroid Build Coastguard Worker     }
2076*61046927SAndroid Build Coastguard Worker }
2077*61046927SAndroid Build Coastguard Worker 
PassFilter(const char * text,const char * text_end) const2078*61046927SAndroid Build Coastguard Worker bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
2079*61046927SAndroid Build Coastguard Worker {
2080*61046927SAndroid Build Coastguard Worker     if (Filters.empty())
2081*61046927SAndroid Build Coastguard Worker         return true;
2082*61046927SAndroid Build Coastguard Worker 
2083*61046927SAndroid Build Coastguard Worker     if (text == NULL)
2084*61046927SAndroid Build Coastguard Worker         text = "";
2085*61046927SAndroid Build Coastguard Worker 
2086*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != Filters.Size; i++)
2087*61046927SAndroid Build Coastguard Worker     {
2088*61046927SAndroid Build Coastguard Worker         const TextRange& f = Filters[i];
2089*61046927SAndroid Build Coastguard Worker         if (f.empty())
2090*61046927SAndroid Build Coastguard Worker             continue;
2091*61046927SAndroid Build Coastguard Worker         if (f.b[0] == '-')
2092*61046927SAndroid Build Coastguard Worker         {
2093*61046927SAndroid Build Coastguard Worker             // Subtract
2094*61046927SAndroid Build Coastguard Worker             if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)
2095*61046927SAndroid Build Coastguard Worker                 return false;
2096*61046927SAndroid Build Coastguard Worker         }
2097*61046927SAndroid Build Coastguard Worker         else
2098*61046927SAndroid Build Coastguard Worker         {
2099*61046927SAndroid Build Coastguard Worker             // Grep
2100*61046927SAndroid Build Coastguard Worker             if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
2101*61046927SAndroid Build Coastguard Worker                 return true;
2102*61046927SAndroid Build Coastguard Worker         }
2103*61046927SAndroid Build Coastguard Worker     }
2104*61046927SAndroid Build Coastguard Worker 
2105*61046927SAndroid Build Coastguard Worker     // Implicit * grep
2106*61046927SAndroid Build Coastguard Worker     if (CountGrep == 0)
2107*61046927SAndroid Build Coastguard Worker         return true;
2108*61046927SAndroid Build Coastguard Worker 
2109*61046927SAndroid Build Coastguard Worker     return false;
2110*61046927SAndroid Build Coastguard Worker }
2111*61046927SAndroid Build Coastguard Worker 
2112*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2113*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiTextBuffer
2114*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2115*61046927SAndroid Build Coastguard Worker 
2116*61046927SAndroid Build Coastguard Worker // On some platform vsnprintf() takes va_list by reference and modifies it.
2117*61046927SAndroid Build Coastguard Worker // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
2118*61046927SAndroid Build Coastguard Worker #ifndef va_copy
2119*61046927SAndroid Build Coastguard Worker #if defined(__GNUC__) || defined(__clang__)
2120*61046927SAndroid Build Coastguard Worker #define va_copy(dest, src) __builtin_va_copy(dest, src)
2121*61046927SAndroid Build Coastguard Worker #else
2122*61046927SAndroid Build Coastguard Worker #define va_copy(dest, src) (dest = src)
2123*61046927SAndroid Build Coastguard Worker #endif
2124*61046927SAndroid Build Coastguard Worker #endif
2125*61046927SAndroid Build Coastguard Worker 
2126*61046927SAndroid Build Coastguard Worker char ImGuiTextBuffer::EmptyString[1] = { 0 };
2127*61046927SAndroid Build Coastguard Worker 
append(const char * str,const char * str_end)2128*61046927SAndroid Build Coastguard Worker void ImGuiTextBuffer::append(const char* str, const char* str_end)
2129*61046927SAndroid Build Coastguard Worker {
2130*61046927SAndroid Build Coastguard Worker     int len = str_end ? (int)(str_end - str) : (int)strlen(str);
2131*61046927SAndroid Build Coastguard Worker 
2132*61046927SAndroid Build Coastguard Worker     // Add zero-terminator the first time
2133*61046927SAndroid Build Coastguard Worker     const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2134*61046927SAndroid Build Coastguard Worker     const int needed_sz = write_off + len;
2135*61046927SAndroid Build Coastguard Worker     if (write_off + len >= Buf.Capacity)
2136*61046927SAndroid Build Coastguard Worker     {
2137*61046927SAndroid Build Coastguard Worker         int new_capacity = Buf.Capacity * 2;
2138*61046927SAndroid Build Coastguard Worker         Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2139*61046927SAndroid Build Coastguard Worker     }
2140*61046927SAndroid Build Coastguard Worker 
2141*61046927SAndroid Build Coastguard Worker     Buf.resize(needed_sz);
2142*61046927SAndroid Build Coastguard Worker     memcpy(&Buf[write_off - 1], str, (size_t)len);
2143*61046927SAndroid Build Coastguard Worker     Buf[write_off - 1 + len] = 0;
2144*61046927SAndroid Build Coastguard Worker }
2145*61046927SAndroid Build Coastguard Worker 
appendf(const char * fmt,...)2146*61046927SAndroid Build Coastguard Worker void ImGuiTextBuffer::appendf(const char* fmt, ...)
2147*61046927SAndroid Build Coastguard Worker {
2148*61046927SAndroid Build Coastguard Worker     va_list args;
2149*61046927SAndroid Build Coastguard Worker     va_start(args, fmt);
2150*61046927SAndroid Build Coastguard Worker     appendfv(fmt, args);
2151*61046927SAndroid Build Coastguard Worker     va_end(args);
2152*61046927SAndroid Build Coastguard Worker }
2153*61046927SAndroid Build Coastguard Worker 
2154*61046927SAndroid Build Coastguard Worker // Helper: Text buffer for logging/accumulating text
appendfv(const char * fmt,va_list args)2155*61046927SAndroid Build Coastguard Worker void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
2156*61046927SAndroid Build Coastguard Worker {
2157*61046927SAndroid Build Coastguard Worker     va_list args_copy;
2158*61046927SAndroid Build Coastguard Worker     va_copy(args_copy, args);
2159*61046927SAndroid Build Coastguard Worker 
2160*61046927SAndroid Build Coastguard Worker     int len = ImFormatStringV(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
2161*61046927SAndroid Build Coastguard Worker     if (len <= 0)
2162*61046927SAndroid Build Coastguard Worker     {
2163*61046927SAndroid Build Coastguard Worker         va_end(args_copy);
2164*61046927SAndroid Build Coastguard Worker         return;
2165*61046927SAndroid Build Coastguard Worker     }
2166*61046927SAndroid Build Coastguard Worker 
2167*61046927SAndroid Build Coastguard Worker     // Add zero-terminator the first time
2168*61046927SAndroid Build Coastguard Worker     const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
2169*61046927SAndroid Build Coastguard Worker     const int needed_sz = write_off + len;
2170*61046927SAndroid Build Coastguard Worker     if (write_off + len >= Buf.Capacity)
2171*61046927SAndroid Build Coastguard Worker     {
2172*61046927SAndroid Build Coastguard Worker         int new_capacity = Buf.Capacity * 2;
2173*61046927SAndroid Build Coastguard Worker         Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
2174*61046927SAndroid Build Coastguard Worker     }
2175*61046927SAndroid Build Coastguard Worker 
2176*61046927SAndroid Build Coastguard Worker     Buf.resize(needed_sz);
2177*61046927SAndroid Build Coastguard Worker     ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
2178*61046927SAndroid Build Coastguard Worker     va_end(args_copy);
2179*61046927SAndroid Build Coastguard Worker }
2180*61046927SAndroid Build Coastguard Worker 
2181*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2182*61046927SAndroid Build Coastguard Worker // [SECTION] ImGuiListClipper
2183*61046927SAndroid Build Coastguard Worker // This is currently not as flexible/powerful as it should be, needs some rework (see TODO)
2184*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2185*61046927SAndroid Build Coastguard Worker 
SetCursorPosYAndSetupDummyPrevLine(float pos_y,float line_height)2186*61046927SAndroid Build Coastguard Worker static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
2187*61046927SAndroid Build Coastguard Worker {
2188*61046927SAndroid Build Coastguard Worker     // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
2189*61046927SAndroid Build Coastguard Worker     // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
2190*61046927SAndroid Build Coastguard Worker     // The clipper should probably have a 4th step to display the last item in a regular manner.
2191*61046927SAndroid Build Coastguard Worker     ImGui::SetCursorPosY(pos_y);
2192*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = ImGui::GetCurrentWindow();
2193*61046927SAndroid Build Coastguard Worker     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.
2194*61046927SAndroid Build Coastguard Worker     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.
2195*61046927SAndroid Build Coastguard Worker     if (window->DC.ColumnsSet)
2196*61046927SAndroid Build Coastguard Worker         window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;           // Setting this so that cell Y position are set properly
2197*61046927SAndroid Build Coastguard Worker }
2198*61046927SAndroid Build Coastguard Worker 
2199*61046927SAndroid Build Coastguard Worker // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
2200*61046927SAndroid Build Coastguard Worker // Use case B: Begin() called from constructor with items_height>0
2201*61046927SAndroid Build Coastguard Worker // 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.
Begin(int count,float items_height)2202*61046927SAndroid Build Coastguard Worker void ImGuiListClipper::Begin(int count, float items_height)
2203*61046927SAndroid Build Coastguard Worker {
2204*61046927SAndroid Build Coastguard Worker     StartPosY = ImGui::GetCursorPosY();
2205*61046927SAndroid Build Coastguard Worker     ItemsHeight = items_height;
2206*61046927SAndroid Build Coastguard Worker     ItemsCount = count;
2207*61046927SAndroid Build Coastguard Worker     StepNo = 0;
2208*61046927SAndroid Build Coastguard Worker     DisplayEnd = DisplayStart = -1;
2209*61046927SAndroid Build Coastguard Worker     if (ItemsHeight > 0.0f)
2210*61046927SAndroid Build Coastguard Worker     {
2211*61046927SAndroid Build Coastguard Worker         ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display
2212*61046927SAndroid Build Coastguard Worker         if (DisplayStart > 0)
2213*61046927SAndroid Build Coastguard Worker             SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor
2214*61046927SAndroid Build Coastguard Worker         StepNo = 2;
2215*61046927SAndroid Build Coastguard Worker     }
2216*61046927SAndroid Build Coastguard Worker }
2217*61046927SAndroid Build Coastguard Worker 
End()2218*61046927SAndroid Build Coastguard Worker void ImGuiListClipper::End()
2219*61046927SAndroid Build Coastguard Worker {
2220*61046927SAndroid Build Coastguard Worker     if (ItemsCount < 0)
2221*61046927SAndroid Build Coastguard Worker         return;
2222*61046927SAndroid Build Coastguard Worker     // 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.
2223*61046927SAndroid Build Coastguard Worker     if (ItemsCount < INT_MAX)
2224*61046927SAndroid Build Coastguard Worker         SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
2225*61046927SAndroid Build Coastguard Worker     ItemsCount = -1;
2226*61046927SAndroid Build Coastguard Worker     StepNo = 3;
2227*61046927SAndroid Build Coastguard Worker }
2228*61046927SAndroid Build Coastguard Worker 
Step()2229*61046927SAndroid Build Coastguard Worker bool ImGuiListClipper::Step()
2230*61046927SAndroid Build Coastguard Worker {
2231*61046927SAndroid Build Coastguard Worker     if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
2232*61046927SAndroid Build Coastguard Worker     {
2233*61046927SAndroid Build Coastguard Worker         ItemsCount = -1;
2234*61046927SAndroid Build Coastguard Worker         return false;
2235*61046927SAndroid Build Coastguard Worker     }
2236*61046927SAndroid Build Coastguard Worker     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.
2237*61046927SAndroid Build Coastguard Worker     {
2238*61046927SAndroid Build Coastguard Worker         DisplayStart = 0;
2239*61046927SAndroid Build Coastguard Worker         DisplayEnd = 1;
2240*61046927SAndroid Build Coastguard Worker         StartPosY = ImGui::GetCursorPosY();
2241*61046927SAndroid Build Coastguard Worker         StepNo = 1;
2242*61046927SAndroid Build Coastguard Worker         return true;
2243*61046927SAndroid Build Coastguard Worker     }
2244*61046927SAndroid Build Coastguard Worker     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.
2245*61046927SAndroid Build Coastguard Worker     {
2246*61046927SAndroid Build Coastguard Worker         if (ItemsCount == 1) { ItemsCount = -1; return false; }
2247*61046927SAndroid Build Coastguard Worker         float items_height = ImGui::GetCursorPosY() - StartPosY;
2248*61046927SAndroid Build Coastguard Worker         IM_ASSERT(items_height > 0.0f);   // If this triggers, it means Item 0 hasn't moved the cursor vertically
2249*61046927SAndroid Build Coastguard Worker         Begin(ItemsCount-1, items_height);
2250*61046927SAndroid Build Coastguard Worker         DisplayStart++;
2251*61046927SAndroid Build Coastguard Worker         DisplayEnd++;
2252*61046927SAndroid Build Coastguard Worker         StepNo = 3;
2253*61046927SAndroid Build Coastguard Worker         return true;
2254*61046927SAndroid Build Coastguard Worker     }
2255*61046927SAndroid Build Coastguard Worker     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.
2256*61046927SAndroid Build Coastguard Worker     {
2257*61046927SAndroid Build Coastguard Worker         IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);
2258*61046927SAndroid Build Coastguard Worker         StepNo = 3;
2259*61046927SAndroid Build Coastguard Worker         return true;
2260*61046927SAndroid Build Coastguard Worker     }
2261*61046927SAndroid Build Coastguard Worker     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.
2262*61046927SAndroid Build Coastguard Worker         End();
2263*61046927SAndroid Build Coastguard Worker     return false;
2264*61046927SAndroid Build Coastguard Worker }
2265*61046927SAndroid Build Coastguard Worker 
2266*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2267*61046927SAndroid Build Coastguard Worker // [SECTION] RENDER HELPERS
2268*61046927SAndroid Build Coastguard Worker // Those (internal) functions are currently quite a legacy mess - their signature and behavior will change.
2269*61046927SAndroid Build Coastguard Worker // Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state.
2270*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2271*61046927SAndroid Build Coastguard Worker 
FindRenderedTextEnd(const char * text,const char * text_end)2272*61046927SAndroid Build Coastguard Worker const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
2273*61046927SAndroid Build Coastguard Worker {
2274*61046927SAndroid Build Coastguard Worker     const char* text_display_end = text;
2275*61046927SAndroid Build Coastguard Worker     if (!text_end)
2276*61046927SAndroid Build Coastguard Worker         text_end = (const char*)-1;
2277*61046927SAndroid Build Coastguard Worker 
2278*61046927SAndroid Build Coastguard Worker     while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
2279*61046927SAndroid Build Coastguard Worker         text_display_end++;
2280*61046927SAndroid Build Coastguard Worker     return text_display_end;
2281*61046927SAndroid Build Coastguard Worker }
2282*61046927SAndroid Build Coastguard Worker 
2283*61046927SAndroid Build Coastguard Worker // Internal ImGui functions to render text
2284*61046927SAndroid Build Coastguard Worker // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
RenderText(ImVec2 pos,const char * text,const char * text_end,bool hide_text_after_hash)2285*61046927SAndroid Build Coastguard Worker void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
2286*61046927SAndroid Build Coastguard Worker {
2287*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2288*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2289*61046927SAndroid Build Coastguard Worker 
2290*61046927SAndroid Build Coastguard Worker     // Hide anything after a '##' string
2291*61046927SAndroid Build Coastguard Worker     const char* text_display_end;
2292*61046927SAndroid Build Coastguard Worker     if (hide_text_after_hash)
2293*61046927SAndroid Build Coastguard Worker     {
2294*61046927SAndroid Build Coastguard Worker         text_display_end = FindRenderedTextEnd(text, text_end);
2295*61046927SAndroid Build Coastguard Worker     }
2296*61046927SAndroid Build Coastguard Worker     else
2297*61046927SAndroid Build Coastguard Worker     {
2298*61046927SAndroid Build Coastguard Worker         if (!text_end)
2299*61046927SAndroid Build Coastguard Worker             text_end = text + strlen(text); // FIXME-OPT
2300*61046927SAndroid Build Coastguard Worker         text_display_end = text_end;
2301*61046927SAndroid Build Coastguard Worker     }
2302*61046927SAndroid Build Coastguard Worker 
2303*61046927SAndroid Build Coastguard Worker     if (text != text_display_end)
2304*61046927SAndroid Build Coastguard Worker     {
2305*61046927SAndroid Build Coastguard Worker         window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
2306*61046927SAndroid Build Coastguard Worker         if (g.LogEnabled)
2307*61046927SAndroid Build Coastguard Worker             LogRenderedText(&pos, text, text_display_end);
2308*61046927SAndroid Build Coastguard Worker     }
2309*61046927SAndroid Build Coastguard Worker }
2310*61046927SAndroid Build Coastguard Worker 
RenderTextWrapped(ImVec2 pos,const char * text,const char * text_end,float wrap_width)2311*61046927SAndroid Build Coastguard Worker void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
2312*61046927SAndroid Build Coastguard Worker {
2313*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2314*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2315*61046927SAndroid Build Coastguard Worker 
2316*61046927SAndroid Build Coastguard Worker     if (!text_end)
2317*61046927SAndroid Build Coastguard Worker         text_end = text + strlen(text); // FIXME-OPT
2318*61046927SAndroid Build Coastguard Worker 
2319*61046927SAndroid Build Coastguard Worker     if (text != text_end)
2320*61046927SAndroid Build Coastguard Worker     {
2321*61046927SAndroid Build Coastguard Worker         window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
2322*61046927SAndroid Build Coastguard Worker         if (g.LogEnabled)
2323*61046927SAndroid Build Coastguard Worker             LogRenderedText(&pos, text, text_end);
2324*61046927SAndroid Build Coastguard Worker     }
2325*61046927SAndroid Build Coastguard Worker }
2326*61046927SAndroid Build Coastguard Worker 
2327*61046927SAndroid Build Coastguard Worker // Default clip_rect uses (pos_min,pos_max)
2328*61046927SAndroid Build Coastguard Worker // Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
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)2329*61046927SAndroid Build Coastguard Worker 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)
2330*61046927SAndroid Build Coastguard Worker {
2331*61046927SAndroid Build Coastguard Worker     // Perform CPU side clipping for single clipped element to avoid using scissor state
2332*61046927SAndroid Build Coastguard Worker     ImVec2 pos = pos_min;
2333*61046927SAndroid Build Coastguard Worker     const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
2334*61046927SAndroid Build Coastguard Worker 
2335*61046927SAndroid Build Coastguard Worker     const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
2336*61046927SAndroid Build Coastguard Worker     const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
2337*61046927SAndroid Build Coastguard Worker     bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
2338*61046927SAndroid Build Coastguard Worker     if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
2339*61046927SAndroid Build Coastguard Worker         need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
2340*61046927SAndroid Build Coastguard Worker 
2341*61046927SAndroid Build Coastguard Worker     // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
2342*61046927SAndroid Build Coastguard Worker     if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
2343*61046927SAndroid Build Coastguard Worker     if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
2344*61046927SAndroid Build Coastguard Worker 
2345*61046927SAndroid Build Coastguard Worker     // Render
2346*61046927SAndroid Build Coastguard Worker     if (need_clipping)
2347*61046927SAndroid Build Coastguard Worker     {
2348*61046927SAndroid Build Coastguard Worker         ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
2349*61046927SAndroid Build Coastguard Worker         draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
2350*61046927SAndroid Build Coastguard Worker     }
2351*61046927SAndroid Build Coastguard Worker     else
2352*61046927SAndroid Build Coastguard Worker     {
2353*61046927SAndroid Build Coastguard Worker         draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
2354*61046927SAndroid Build Coastguard Worker     }
2355*61046927SAndroid Build Coastguard Worker }
2356*61046927SAndroid Build Coastguard Worker 
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)2357*61046927SAndroid Build Coastguard Worker 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)
2358*61046927SAndroid Build Coastguard Worker {
2359*61046927SAndroid Build Coastguard Worker     // Hide anything after a '##' string
2360*61046927SAndroid Build Coastguard Worker     const char* text_display_end = FindRenderedTextEnd(text, text_end);
2361*61046927SAndroid Build Coastguard Worker     const int text_len = (int)(text_display_end - text);
2362*61046927SAndroid Build Coastguard Worker     if (text_len == 0)
2363*61046927SAndroid Build Coastguard Worker         return;
2364*61046927SAndroid Build Coastguard Worker 
2365*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2366*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2367*61046927SAndroid Build Coastguard Worker     RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
2368*61046927SAndroid Build Coastguard Worker     if (g.LogEnabled)
2369*61046927SAndroid Build Coastguard Worker         LogRenderedText(&pos_min, text, text_display_end);
2370*61046927SAndroid Build Coastguard Worker }
2371*61046927SAndroid Build Coastguard Worker 
2372*61046927SAndroid Build Coastguard Worker // Render a rectangle shaped with optional rounding and borders
RenderFrame(ImVec2 p_min,ImVec2 p_max,ImU32 fill_col,bool border,float rounding)2373*61046927SAndroid Build Coastguard Worker void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
2374*61046927SAndroid Build Coastguard Worker {
2375*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2376*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2377*61046927SAndroid Build Coastguard Worker     window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
2378*61046927SAndroid Build Coastguard Worker     const float border_size = g.Style.FrameBorderSize;
2379*61046927SAndroid Build Coastguard Worker     if (border && border_size > 0.0f)
2380*61046927SAndroid Build Coastguard Worker     {
2381*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2382*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2383*61046927SAndroid Build Coastguard Worker     }
2384*61046927SAndroid Build Coastguard Worker }
2385*61046927SAndroid Build Coastguard Worker 
RenderFrameBorder(ImVec2 p_min,ImVec2 p_max,float rounding)2386*61046927SAndroid Build Coastguard Worker void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
2387*61046927SAndroid Build Coastguard Worker {
2388*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2389*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2390*61046927SAndroid Build Coastguard Worker     const float border_size = g.Style.FrameBorderSize;
2391*61046927SAndroid Build Coastguard Worker     if (border_size > 0.0f)
2392*61046927SAndroid Build Coastguard Worker     {
2393*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2394*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2395*61046927SAndroid Build Coastguard Worker     }
2396*61046927SAndroid Build Coastguard Worker }
2397*61046927SAndroid Build Coastguard Worker 
2398*61046927SAndroid Build Coastguard Worker // 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
RenderArrow(ImVec2 p_min,ImGuiDir dir,float scale)2399*61046927SAndroid Build Coastguard Worker void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale)
2400*61046927SAndroid Build Coastguard Worker {
2401*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2402*61046927SAndroid Build Coastguard Worker 
2403*61046927SAndroid Build Coastguard Worker     const float h = g.FontSize * 1.00f;
2404*61046927SAndroid Build Coastguard Worker     float r = h * 0.40f * scale;
2405*61046927SAndroid Build Coastguard Worker     ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale);
2406*61046927SAndroid Build Coastguard Worker 
2407*61046927SAndroid Build Coastguard Worker     ImVec2 a, b, c;
2408*61046927SAndroid Build Coastguard Worker     switch (dir)
2409*61046927SAndroid Build Coastguard Worker     {
2410*61046927SAndroid Build Coastguard Worker     case ImGuiDir_Up:
2411*61046927SAndroid Build Coastguard Worker     case ImGuiDir_Down:
2412*61046927SAndroid Build Coastguard Worker         if (dir == ImGuiDir_Up) r = -r;
2413*61046927SAndroid Build Coastguard Worker         a = ImVec2(+0.000f,+0.750f) * r;
2414*61046927SAndroid Build Coastguard Worker         b = ImVec2(-0.866f,-0.750f) * r;
2415*61046927SAndroid Build Coastguard Worker         c = ImVec2(+0.866f,-0.750f) * r;
2416*61046927SAndroid Build Coastguard Worker         break;
2417*61046927SAndroid Build Coastguard Worker     case ImGuiDir_Left:
2418*61046927SAndroid Build Coastguard Worker     case ImGuiDir_Right:
2419*61046927SAndroid Build Coastguard Worker         if (dir == ImGuiDir_Left) r = -r;
2420*61046927SAndroid Build Coastguard Worker         a = ImVec2(+0.750f,+0.000f) * r;
2421*61046927SAndroid Build Coastguard Worker         b = ImVec2(-0.750f,+0.866f) * r;
2422*61046927SAndroid Build Coastguard Worker         c = ImVec2(-0.750f,-0.866f) * r;
2423*61046927SAndroid Build Coastguard Worker         break;
2424*61046927SAndroid Build Coastguard Worker     case ImGuiDir_None:
2425*61046927SAndroid Build Coastguard Worker     case ImGuiDir_COUNT:
2426*61046927SAndroid Build Coastguard Worker         IM_ASSERT(0);
2427*61046927SAndroid Build Coastguard Worker         break;
2428*61046927SAndroid Build Coastguard Worker     }
2429*61046927SAndroid Build Coastguard Worker 
2430*61046927SAndroid Build Coastguard Worker     g.CurrentWindow->DrawList->AddTriangleFilled(center + a, center + b, center + c, GetColorU32(ImGuiCol_Text));
2431*61046927SAndroid Build Coastguard Worker }
2432*61046927SAndroid Build Coastguard Worker 
RenderBullet(ImVec2 pos)2433*61046927SAndroid Build Coastguard Worker void ImGui::RenderBullet(ImVec2 pos)
2434*61046927SAndroid Build Coastguard Worker {
2435*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2436*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2437*61046927SAndroid Build Coastguard Worker     window->DrawList->AddCircleFilled(pos, g.FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
2438*61046927SAndroid Build Coastguard Worker }
2439*61046927SAndroid Build Coastguard Worker 
RenderCheckMark(ImVec2 pos,ImU32 col,float sz)2440*61046927SAndroid Build Coastguard Worker void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz)
2441*61046927SAndroid Build Coastguard Worker {
2442*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2443*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2444*61046927SAndroid Build Coastguard Worker 
2445*61046927SAndroid Build Coastguard Worker     float thickness = ImMax(sz / 5.0f, 1.0f);
2446*61046927SAndroid Build Coastguard Worker     sz -= thickness*0.5f;
2447*61046927SAndroid Build Coastguard Worker     pos += ImVec2(thickness*0.25f, thickness*0.25f);
2448*61046927SAndroid Build Coastguard Worker 
2449*61046927SAndroid Build Coastguard Worker     float third = sz / 3.0f;
2450*61046927SAndroid Build Coastguard Worker     float bx = pos.x + third;
2451*61046927SAndroid Build Coastguard Worker     float by = pos.y + sz - third*0.5f;
2452*61046927SAndroid Build Coastguard Worker     window->DrawList->PathLineTo(ImVec2(bx - third, by - third));
2453*61046927SAndroid Build Coastguard Worker     window->DrawList->PathLineTo(ImVec2(bx, by));
2454*61046927SAndroid Build Coastguard Worker     window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2));
2455*61046927SAndroid Build Coastguard Worker     window->DrawList->PathStroke(col, false, thickness);
2456*61046927SAndroid Build Coastguard Worker }
2457*61046927SAndroid Build Coastguard Worker 
RenderNavHighlight(const ImRect & bb,ImGuiID id,ImGuiNavHighlightFlags flags)2458*61046927SAndroid Build Coastguard Worker void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
2459*61046927SAndroid Build Coastguard Worker {
2460*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2461*61046927SAndroid Build Coastguard Worker     if (id != g.NavId)
2462*61046927SAndroid Build Coastguard Worker         return;
2463*61046927SAndroid Build Coastguard Worker     if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
2464*61046927SAndroid Build Coastguard Worker         return;
2465*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2466*61046927SAndroid Build Coastguard Worker     if (window->DC.NavHideHighlightOneFrame)
2467*61046927SAndroid Build Coastguard Worker         return;
2468*61046927SAndroid Build Coastguard Worker 
2469*61046927SAndroid Build Coastguard Worker     float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
2470*61046927SAndroid Build Coastguard Worker     ImRect display_rect = bb;
2471*61046927SAndroid Build Coastguard Worker     display_rect.ClipWith(window->ClipRect);
2472*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiNavHighlightFlags_TypeDefault)
2473*61046927SAndroid Build Coastguard Worker     {
2474*61046927SAndroid Build Coastguard Worker         const float THICKNESS = 2.0f;
2475*61046927SAndroid Build Coastguard Worker         const float DISTANCE = 3.0f + THICKNESS * 0.5f;
2476*61046927SAndroid Build Coastguard Worker         display_rect.Expand(ImVec2(DISTANCE,DISTANCE));
2477*61046927SAndroid Build Coastguard Worker         bool fully_visible = window->ClipRect.Contains(display_rect);
2478*61046927SAndroid Build Coastguard Worker         if (!fully_visible)
2479*61046927SAndroid Build Coastguard Worker             window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
2480*61046927SAndroid Build Coastguard Worker         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);
2481*61046927SAndroid Build Coastguard Worker         if (!fully_visible)
2482*61046927SAndroid Build Coastguard Worker             window->DrawList->PopClipRect();
2483*61046927SAndroid Build Coastguard Worker     }
2484*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiNavHighlightFlags_TypeThin)
2485*61046927SAndroid Build Coastguard Worker     {
2486*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
2487*61046927SAndroid Build Coastguard Worker     }
2488*61046927SAndroid Build Coastguard Worker }
2489*61046927SAndroid Build Coastguard Worker 
2490*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2491*61046927SAndroid Build Coastguard Worker // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
2492*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
2493*61046927SAndroid Build Coastguard Worker 
2494*61046927SAndroid Build Coastguard Worker // ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
ImGuiWindow(ImGuiContext * context,const char * name)2495*61046927SAndroid Build Coastguard Worker ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
2496*61046927SAndroid Build Coastguard Worker     : DrawListInst(&context->DrawListSharedData)
2497*61046927SAndroid Build Coastguard Worker {
2498*61046927SAndroid Build Coastguard Worker     Name = ImStrdup(name);
2499*61046927SAndroid Build Coastguard Worker     ID = ImHashStr(name, 0);
2500*61046927SAndroid Build Coastguard Worker     IDStack.push_back(ID);
2501*61046927SAndroid Build Coastguard Worker     Flags = ImGuiWindowFlags_None;
2502*61046927SAndroid Build Coastguard Worker     Pos = ImVec2(0.0f, 0.0f);
2503*61046927SAndroid Build Coastguard Worker     Size = SizeFull = ImVec2(0.0f, 0.0f);
2504*61046927SAndroid Build Coastguard Worker     SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
2505*61046927SAndroid Build Coastguard Worker     WindowPadding = ImVec2(0.0f, 0.0f);
2506*61046927SAndroid Build Coastguard Worker     WindowRounding = 0.0f;
2507*61046927SAndroid Build Coastguard Worker     WindowBorderSize = 0.0f;
2508*61046927SAndroid Build Coastguard Worker     NameBufLen = (int)strlen(name) + 1;
2509*61046927SAndroid Build Coastguard Worker     MoveId = GetID("#MOVE");
2510*61046927SAndroid Build Coastguard Worker     ChildId = 0;
2511*61046927SAndroid Build Coastguard Worker     Scroll = ImVec2(0.0f, 0.0f);
2512*61046927SAndroid Build Coastguard Worker     ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
2513*61046927SAndroid Build Coastguard Worker     ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
2514*61046927SAndroid Build Coastguard Worker     ScrollbarSizes = ImVec2(0.0f, 0.0f);
2515*61046927SAndroid Build Coastguard Worker     ScrollbarX = ScrollbarY = false;
2516*61046927SAndroid Build Coastguard Worker     Active = WasActive = false;
2517*61046927SAndroid Build Coastguard Worker     WriteAccessed = false;
2518*61046927SAndroid Build Coastguard Worker     Collapsed = false;
2519*61046927SAndroid Build Coastguard Worker     WantCollapseToggle = false;
2520*61046927SAndroid Build Coastguard Worker     SkipItems = false;
2521*61046927SAndroid Build Coastguard Worker     Appearing = false;
2522*61046927SAndroid Build Coastguard Worker     Hidden = false;
2523*61046927SAndroid Build Coastguard Worker     HasCloseButton = false;
2524*61046927SAndroid Build Coastguard Worker     ResizeBorderHeld = -1;
2525*61046927SAndroid Build Coastguard Worker     BeginCount = 0;
2526*61046927SAndroid Build Coastguard Worker     BeginOrderWithinParent = -1;
2527*61046927SAndroid Build Coastguard Worker     BeginOrderWithinContext = -1;
2528*61046927SAndroid Build Coastguard Worker     PopupId = 0;
2529*61046927SAndroid Build Coastguard Worker     AutoFitFramesX = AutoFitFramesY = -1;
2530*61046927SAndroid Build Coastguard Worker     AutoFitOnlyGrows = false;
2531*61046927SAndroid Build Coastguard Worker     AutoFitChildAxises = 0x00;
2532*61046927SAndroid Build Coastguard Worker     AutoPosLastDirection = ImGuiDir_None;
2533*61046927SAndroid Build Coastguard Worker     HiddenFramesRegular = HiddenFramesForResize = 0;
2534*61046927SAndroid Build Coastguard Worker     SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
2535*61046927SAndroid Build Coastguard Worker     SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
2536*61046927SAndroid Build Coastguard Worker 
2537*61046927SAndroid Build Coastguard Worker     LastFrameActive = -1;
2538*61046927SAndroid Build Coastguard Worker     ItemWidthDefault = 0.0f;
2539*61046927SAndroid Build Coastguard Worker     FontWindowScale = 1.0f;
2540*61046927SAndroid Build Coastguard Worker     SettingsIdx = -1;
2541*61046927SAndroid Build Coastguard Worker 
2542*61046927SAndroid Build Coastguard Worker     DrawList = &DrawListInst;
2543*61046927SAndroid Build Coastguard Worker     DrawList->_OwnerName = Name;
2544*61046927SAndroid Build Coastguard Worker     ParentWindow = NULL;
2545*61046927SAndroid Build Coastguard Worker     RootWindow = NULL;
2546*61046927SAndroid Build Coastguard Worker     RootWindowForTitleBarHighlight = NULL;
2547*61046927SAndroid Build Coastguard Worker     RootWindowForNav = NULL;
2548*61046927SAndroid Build Coastguard Worker 
2549*61046927SAndroid Build Coastguard Worker     NavLastIds[0] = NavLastIds[1] = 0;
2550*61046927SAndroid Build Coastguard Worker     NavRectRel[0] = NavRectRel[1] = ImRect();
2551*61046927SAndroid Build Coastguard Worker     NavLastChildNavWindow = NULL;
2552*61046927SAndroid Build Coastguard Worker 
2553*61046927SAndroid Build Coastguard Worker     FocusIdxAllCounter = FocusIdxTabCounter = -1;
2554*61046927SAndroid Build Coastguard Worker     FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
2555*61046927SAndroid Build Coastguard Worker     FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
2556*61046927SAndroid Build Coastguard Worker }
2557*61046927SAndroid Build Coastguard Worker 
~ImGuiWindow()2558*61046927SAndroid Build Coastguard Worker ImGuiWindow::~ImGuiWindow()
2559*61046927SAndroid Build Coastguard Worker {
2560*61046927SAndroid Build Coastguard Worker     IM_ASSERT(DrawList == &DrawListInst);
2561*61046927SAndroid Build Coastguard Worker     IM_DELETE(Name);
2562*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != ColumnsStorage.Size; i++)
2563*61046927SAndroid Build Coastguard Worker         ColumnsStorage[i].~ImGuiColumnsSet();
2564*61046927SAndroid Build Coastguard Worker }
2565*61046927SAndroid Build Coastguard Worker 
GetID(const char * str,const char * str_end)2566*61046927SAndroid Build Coastguard Worker ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
2567*61046927SAndroid Build Coastguard Worker {
2568*61046927SAndroid Build Coastguard Worker     ImGuiID seed = IDStack.back();
2569*61046927SAndroid Build Coastguard Worker     ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
2570*61046927SAndroid Build Coastguard Worker     ImGui::KeepAliveID(id);
2571*61046927SAndroid Build Coastguard Worker     return id;
2572*61046927SAndroid Build Coastguard Worker }
2573*61046927SAndroid Build Coastguard Worker 
GetID(const void * ptr)2574*61046927SAndroid Build Coastguard Worker ImGuiID ImGuiWindow::GetID(const void* ptr)
2575*61046927SAndroid Build Coastguard Worker {
2576*61046927SAndroid Build Coastguard Worker     ImGuiID seed = IDStack.back();
2577*61046927SAndroid Build Coastguard Worker     ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
2578*61046927SAndroid Build Coastguard Worker     ImGui::KeepAliveID(id);
2579*61046927SAndroid Build Coastguard Worker     return id;
2580*61046927SAndroid Build Coastguard Worker }
2581*61046927SAndroid Build Coastguard Worker 
GetIDNoKeepAlive(const char * str,const char * str_end)2582*61046927SAndroid Build Coastguard Worker ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
2583*61046927SAndroid Build Coastguard Worker {
2584*61046927SAndroid Build Coastguard Worker     ImGuiID seed = IDStack.back();
2585*61046927SAndroid Build Coastguard Worker     return ImHashStr(str, str_end ? (str_end - str) : 0, seed);
2586*61046927SAndroid Build Coastguard Worker }
2587*61046927SAndroid Build Coastguard Worker 
GetIDNoKeepAlive(const void * ptr)2588*61046927SAndroid Build Coastguard Worker ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
2589*61046927SAndroid Build Coastguard Worker {
2590*61046927SAndroid Build Coastguard Worker     ImGuiID seed = IDStack.back();
2591*61046927SAndroid Build Coastguard Worker     return ImHashData(&ptr, sizeof(void*), seed);
2592*61046927SAndroid Build Coastguard Worker }
2593*61046927SAndroid Build Coastguard Worker 
2594*61046927SAndroid Build Coastguard Worker // This is only used in rare/specific situations to manufacture an ID out of nowhere.
GetIDFromRectangle(const ImRect & r_abs)2595*61046927SAndroid Build Coastguard Worker ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
2596*61046927SAndroid Build Coastguard Worker {
2597*61046927SAndroid Build Coastguard Worker     ImGuiID seed = IDStack.back();
2598*61046927SAndroid Build Coastguard Worker     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) };
2599*61046927SAndroid Build Coastguard Worker     ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed);
2600*61046927SAndroid Build Coastguard Worker     ImGui::KeepAliveID(id);
2601*61046927SAndroid Build Coastguard Worker     return id;
2602*61046927SAndroid Build Coastguard Worker }
2603*61046927SAndroid Build Coastguard Worker 
SetCurrentWindow(ImGuiWindow * window)2604*61046927SAndroid Build Coastguard Worker static void SetCurrentWindow(ImGuiWindow* window)
2605*61046927SAndroid Build Coastguard Worker {
2606*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2607*61046927SAndroid Build Coastguard Worker     g.CurrentWindow = window;
2608*61046927SAndroid Build Coastguard Worker     if (window)
2609*61046927SAndroid Build Coastguard Worker         g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
2610*61046927SAndroid Build Coastguard Worker }
2611*61046927SAndroid Build Coastguard Worker 
SetNavID(ImGuiID id,int nav_layer)2612*61046927SAndroid Build Coastguard Worker void ImGui::SetNavID(ImGuiID id, int nav_layer)
2613*61046927SAndroid Build Coastguard Worker {
2614*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2615*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavWindow);
2616*61046927SAndroid Build Coastguard Worker     IM_ASSERT(nav_layer == 0 || nav_layer == 1);
2617*61046927SAndroid Build Coastguard Worker     g.NavId = id;
2618*61046927SAndroid Build Coastguard Worker     g.NavWindow->NavLastIds[nav_layer] = id;
2619*61046927SAndroid Build Coastguard Worker }
2620*61046927SAndroid Build Coastguard Worker 
SetNavIDWithRectRel(ImGuiID id,int nav_layer,const ImRect & rect_rel)2621*61046927SAndroid Build Coastguard Worker void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel)
2622*61046927SAndroid Build Coastguard Worker {
2623*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2624*61046927SAndroid Build Coastguard Worker     SetNavID(id, nav_layer);
2625*61046927SAndroid Build Coastguard Worker     g.NavWindow->NavRectRel[nav_layer] = rect_rel;
2626*61046927SAndroid Build Coastguard Worker     g.NavMousePosDirty = true;
2627*61046927SAndroid Build Coastguard Worker     g.NavDisableHighlight = false;
2628*61046927SAndroid Build Coastguard Worker     g.NavDisableMouseHover = true;
2629*61046927SAndroid Build Coastguard Worker }
2630*61046927SAndroid Build Coastguard Worker 
SetActiveID(ImGuiID id,ImGuiWindow * window)2631*61046927SAndroid Build Coastguard Worker void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
2632*61046927SAndroid Build Coastguard Worker {
2633*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2634*61046927SAndroid Build Coastguard Worker     g.ActiveIdIsJustActivated = (g.ActiveId != id);
2635*61046927SAndroid Build Coastguard Worker     if (g.ActiveIdIsJustActivated)
2636*61046927SAndroid Build Coastguard Worker     {
2637*61046927SAndroid Build Coastguard Worker         g.ActiveIdTimer = 0.0f;
2638*61046927SAndroid Build Coastguard Worker         g.ActiveIdHasBeenPressed = false;
2639*61046927SAndroid Build Coastguard Worker         g.ActiveIdHasBeenEdited = false;
2640*61046927SAndroid Build Coastguard Worker         if (id != 0)
2641*61046927SAndroid Build Coastguard Worker         {
2642*61046927SAndroid Build Coastguard Worker             g.LastActiveId = id;
2643*61046927SAndroid Build Coastguard Worker             g.LastActiveIdTimer = 0.0f;
2644*61046927SAndroid Build Coastguard Worker         }
2645*61046927SAndroid Build Coastguard Worker     }
2646*61046927SAndroid Build Coastguard Worker     g.ActiveId = id;
2647*61046927SAndroid Build Coastguard Worker     g.ActiveIdAllowNavDirFlags = 0;
2648*61046927SAndroid Build Coastguard Worker     g.ActiveIdBlockNavInputFlags = 0;
2649*61046927SAndroid Build Coastguard Worker     g.ActiveIdAllowOverlap = false;
2650*61046927SAndroid Build Coastguard Worker     g.ActiveIdWindow = window;
2651*61046927SAndroid Build Coastguard Worker     if (id)
2652*61046927SAndroid Build Coastguard Worker     {
2653*61046927SAndroid Build Coastguard Worker         g.ActiveIdIsAlive = id;
2654*61046927SAndroid Build Coastguard Worker         g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
2655*61046927SAndroid Build Coastguard Worker     }
2656*61046927SAndroid Build Coastguard Worker }
2657*61046927SAndroid Build Coastguard Worker 
2658*61046927SAndroid Build Coastguard Worker // FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring.
SetFocusID(ImGuiID id,ImGuiWindow * window)2659*61046927SAndroid Build Coastguard Worker void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
2660*61046927SAndroid Build Coastguard Worker {
2661*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2662*61046927SAndroid Build Coastguard Worker     IM_ASSERT(id != 0);
2663*61046927SAndroid Build Coastguard Worker 
2664*61046927SAndroid Build Coastguard Worker     // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it.
2665*61046927SAndroid Build Coastguard Worker     const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
2666*61046927SAndroid Build Coastguard Worker     if (g.NavWindow != window)
2667*61046927SAndroid Build Coastguard Worker         g.NavInitRequest = false;
2668*61046927SAndroid Build Coastguard Worker     g.NavId = id;
2669*61046927SAndroid Build Coastguard Worker     g.NavWindow = window;
2670*61046927SAndroid Build Coastguard Worker     g.NavLayer = nav_layer;
2671*61046927SAndroid Build Coastguard Worker     window->NavLastIds[nav_layer] = id;
2672*61046927SAndroid Build Coastguard Worker     if (window->DC.LastItemId == id)
2673*61046927SAndroid Build Coastguard Worker         window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
2674*61046927SAndroid Build Coastguard Worker 
2675*61046927SAndroid Build Coastguard Worker     if (g.ActiveIdSource == ImGuiInputSource_Nav)
2676*61046927SAndroid Build Coastguard Worker         g.NavDisableMouseHover = true;
2677*61046927SAndroid Build Coastguard Worker     else
2678*61046927SAndroid Build Coastguard Worker         g.NavDisableHighlight = true;
2679*61046927SAndroid Build Coastguard Worker }
2680*61046927SAndroid Build Coastguard Worker 
ClearActiveID()2681*61046927SAndroid Build Coastguard Worker void ImGui::ClearActiveID()
2682*61046927SAndroid Build Coastguard Worker {
2683*61046927SAndroid Build Coastguard Worker     SetActiveID(0, NULL);
2684*61046927SAndroid Build Coastguard Worker }
2685*61046927SAndroid Build Coastguard Worker 
SetHoveredID(ImGuiID id)2686*61046927SAndroid Build Coastguard Worker void ImGui::SetHoveredID(ImGuiID id)
2687*61046927SAndroid Build Coastguard Worker {
2688*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2689*61046927SAndroid Build Coastguard Worker     g.HoveredId = id;
2690*61046927SAndroid Build Coastguard Worker     g.HoveredIdAllowOverlap = false;
2691*61046927SAndroid Build Coastguard Worker     if (id != 0 && g.HoveredIdPreviousFrame != id)
2692*61046927SAndroid Build Coastguard Worker         g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
2693*61046927SAndroid Build Coastguard Worker }
2694*61046927SAndroid Build Coastguard Worker 
GetHoveredID()2695*61046927SAndroid Build Coastguard Worker ImGuiID ImGui::GetHoveredID()
2696*61046927SAndroid Build Coastguard Worker {
2697*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2698*61046927SAndroid Build Coastguard Worker     return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
2699*61046927SAndroid Build Coastguard Worker }
2700*61046927SAndroid Build Coastguard Worker 
KeepAliveID(ImGuiID id)2701*61046927SAndroid Build Coastguard Worker void ImGui::KeepAliveID(ImGuiID id)
2702*61046927SAndroid Build Coastguard Worker {
2703*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2704*61046927SAndroid Build Coastguard Worker     if (g.ActiveId == id)
2705*61046927SAndroid Build Coastguard Worker         g.ActiveIdIsAlive = id;
2706*61046927SAndroid Build Coastguard Worker     if (g.ActiveIdPreviousFrame == id)
2707*61046927SAndroid Build Coastguard Worker         g.ActiveIdPreviousFrameIsAlive = true;
2708*61046927SAndroid Build Coastguard Worker }
2709*61046927SAndroid Build Coastguard Worker 
MarkItemEdited(ImGuiID id)2710*61046927SAndroid Build Coastguard Worker void ImGui::MarkItemEdited(ImGuiID id)
2711*61046927SAndroid Build Coastguard Worker {
2712*61046927SAndroid Build Coastguard Worker     // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
2713*61046927SAndroid Build Coastguard Worker     // 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.
2714*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2715*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
2716*61046927SAndroid Build Coastguard Worker     IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
2717*61046927SAndroid Build Coastguard Worker     //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
2718*61046927SAndroid Build Coastguard Worker     g.ActiveIdHasBeenEdited = true;
2719*61046927SAndroid Build Coastguard Worker     g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
2720*61046927SAndroid Build Coastguard Worker }
2721*61046927SAndroid Build Coastguard Worker 
IsWindowContentHoverable(ImGuiWindow * window,ImGuiHoveredFlags flags)2722*61046927SAndroid Build Coastguard Worker static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
2723*61046927SAndroid Build Coastguard Worker {
2724*61046927SAndroid Build Coastguard Worker     // An active popup disable hovering on other windows (apart from its own children)
2725*61046927SAndroid Build Coastguard Worker     // FIXME-OPT: This could be cached/stored within the window.
2726*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2727*61046927SAndroid Build Coastguard Worker     if (g.NavWindow)
2728*61046927SAndroid Build Coastguard Worker         if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
2729*61046927SAndroid Build Coastguard Worker             if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
2730*61046927SAndroid Build Coastguard Worker             {
2731*61046927SAndroid Build Coastguard Worker                 // For the purpose of those flags we differentiate "standard popup" from "modal popup"
2732*61046927SAndroid Build Coastguard Worker                 // NB: The order of those two tests is important because Modal windows are also Popups.
2733*61046927SAndroid Build Coastguard Worker                 if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
2734*61046927SAndroid Build Coastguard Worker                     return false;
2735*61046927SAndroid Build Coastguard Worker                 if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
2736*61046927SAndroid Build Coastguard Worker                     return false;
2737*61046927SAndroid Build Coastguard Worker             }
2738*61046927SAndroid Build Coastguard Worker 
2739*61046927SAndroid Build Coastguard Worker     return true;
2740*61046927SAndroid Build Coastguard Worker }
2741*61046927SAndroid Build Coastguard Worker 
2742*61046927SAndroid Build Coastguard Worker // Advance cursor given item size for layout.
ItemSize(const ImVec2 & size,float text_offset_y)2743*61046927SAndroid Build Coastguard Worker void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
2744*61046927SAndroid Build Coastguard Worker {
2745*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2746*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2747*61046927SAndroid Build Coastguard Worker     if (window->SkipItems)
2748*61046927SAndroid Build Coastguard Worker         return;
2749*61046927SAndroid Build Coastguard Worker 
2750*61046927SAndroid Build Coastguard Worker     // Always align ourselves on pixel boundaries
2751*61046927SAndroid Build Coastguard Worker     const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
2752*61046927SAndroid Build Coastguard Worker     const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
2753*61046927SAndroid Build Coastguard Worker     //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]
2754*61046927SAndroid Build Coastguard Worker     window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
2755*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
2756*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
2757*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
2758*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
2759*61046927SAndroid Build Coastguard Worker     //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
2760*61046927SAndroid Build Coastguard Worker 
2761*61046927SAndroid Build Coastguard Worker     window->DC.PrevLineSize.y = line_height;
2762*61046927SAndroid Build Coastguard Worker     window->DC.PrevLineTextBaseOffset = text_base_offset;
2763*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
2764*61046927SAndroid Build Coastguard Worker 
2765*61046927SAndroid Build Coastguard Worker     // Horizontal layout mode
2766*61046927SAndroid Build Coastguard Worker     if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
2767*61046927SAndroid Build Coastguard Worker         SameLine();
2768*61046927SAndroid Build Coastguard Worker }
2769*61046927SAndroid Build Coastguard Worker 
ItemSize(const ImRect & bb,float text_offset_y)2770*61046927SAndroid Build Coastguard Worker void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
2771*61046927SAndroid Build Coastguard Worker {
2772*61046927SAndroid Build Coastguard Worker     ItemSize(bb.GetSize(), text_offset_y);
2773*61046927SAndroid Build Coastguard Worker }
2774*61046927SAndroid Build Coastguard Worker 
2775*61046927SAndroid Build Coastguard Worker // Declare item bounding box for clipping and interaction.
2776*61046927SAndroid Build Coastguard Worker // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
2777*61046927SAndroid Build Coastguard Worker // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
ItemAdd(const ImRect & bb,ImGuiID id,const ImRect * nav_bb_arg)2778*61046927SAndroid Build Coastguard Worker bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
2779*61046927SAndroid Build Coastguard Worker {
2780*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2781*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2782*61046927SAndroid Build Coastguard Worker 
2783*61046927SAndroid Build Coastguard Worker     if (id != 0)
2784*61046927SAndroid Build Coastguard Worker     {
2785*61046927SAndroid Build Coastguard Worker         // Navigation processing runs prior to clipping early-out
2786*61046927SAndroid Build Coastguard Worker         //  (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
2787*61046927SAndroid Build Coastguard Worker         //  (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.
2788*61046927SAndroid Build Coastguard Worker         //      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.
2789*61046927SAndroid Build Coastguard Worker         //      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)
2790*61046927SAndroid Build Coastguard Worker         window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask;
2791*61046927SAndroid Build Coastguard Worker         if (g.NavId == id || g.NavAnyRequest)
2792*61046927SAndroid Build Coastguard Worker             if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
2793*61046927SAndroid Build Coastguard Worker                 if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
2794*61046927SAndroid Build Coastguard Worker                     NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id);
2795*61046927SAndroid Build Coastguard Worker     }
2796*61046927SAndroid Build Coastguard Worker 
2797*61046927SAndroid Build Coastguard Worker     window->DC.LastItemId = id;
2798*61046927SAndroid Build Coastguard Worker     window->DC.LastItemRect = bb;
2799*61046927SAndroid Build Coastguard Worker     window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
2800*61046927SAndroid Build Coastguard Worker 
2801*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_ENABLE_TEST_ENGINE
2802*61046927SAndroid Build Coastguard Worker     if (id != 0)
2803*61046927SAndroid Build Coastguard Worker         ImGuiTestEngineHook_ItemAdd(&g, nav_bb_arg ? *nav_bb_arg : bb, id);
2804*61046927SAndroid Build Coastguard Worker #endif
2805*61046927SAndroid Build Coastguard Worker 
2806*61046927SAndroid Build Coastguard Worker     // Clipping test
2807*61046927SAndroid Build Coastguard Worker     const bool is_clipped = IsClippedEx(bb, id, false);
2808*61046927SAndroid Build Coastguard Worker     if (is_clipped)
2809*61046927SAndroid Build Coastguard Worker         return false;
2810*61046927SAndroid Build Coastguard Worker     //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
2811*61046927SAndroid Build Coastguard Worker 
2812*61046927SAndroid Build Coastguard Worker     // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
2813*61046927SAndroid Build Coastguard Worker     if (IsMouseHoveringRect(bb.Min, bb.Max))
2814*61046927SAndroid Build Coastguard Worker         window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
2815*61046927SAndroid Build Coastguard Worker     return true;
2816*61046927SAndroid Build Coastguard Worker }
2817*61046927SAndroid Build Coastguard Worker 
2818*61046927SAndroid Build Coastguard Worker // This is roughly matching the behavior of internal-facing ItemHoverable()
2819*61046927SAndroid Build Coastguard Worker // - 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()
2820*61046927SAndroid Build Coastguard Worker // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
IsItemHovered(ImGuiHoveredFlags flags)2821*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
2822*61046927SAndroid Build Coastguard Worker {
2823*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2824*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2825*61046927SAndroid Build Coastguard Worker     if (g.NavDisableMouseHover && !g.NavDisableHighlight)
2826*61046927SAndroid Build Coastguard Worker         return IsItemFocused();
2827*61046927SAndroid Build Coastguard Worker 
2828*61046927SAndroid Build Coastguard Worker     // Test for bounding box overlap, as updated as ItemAdd()
2829*61046927SAndroid Build Coastguard Worker     if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
2830*61046927SAndroid Build Coastguard Worker         return false;
2831*61046927SAndroid Build Coastguard Worker     IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0);   // Flags not supported by this function
2832*61046927SAndroid Build Coastguard Worker 
2833*61046927SAndroid Build Coastguard Worker     // Test if we are hovering the right window (our window could be behind another window)
2834*61046927SAndroid Build Coastguard Worker     // [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.
2835*61046927SAndroid Build Coastguard Worker     // 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.
2836*61046927SAndroid Build Coastguard Worker     //if (g.HoveredWindow != window)
2837*61046927SAndroid Build Coastguard Worker     //    return false;
2838*61046927SAndroid Build Coastguard Worker     if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
2839*61046927SAndroid Build Coastguard Worker         return false;
2840*61046927SAndroid Build Coastguard Worker 
2841*61046927SAndroid Build Coastguard Worker     // Test if another item is active (e.g. being dragged)
2842*61046927SAndroid Build Coastguard Worker     if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
2843*61046927SAndroid Build Coastguard Worker         if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
2844*61046927SAndroid Build Coastguard Worker             return false;
2845*61046927SAndroid Build Coastguard Worker 
2846*61046927SAndroid Build Coastguard Worker     // Test if interactions on this window are blocked by an active popup or modal
2847*61046927SAndroid Build Coastguard Worker     if (!IsWindowContentHoverable(window, flags))
2848*61046927SAndroid Build Coastguard Worker         return false;
2849*61046927SAndroid Build Coastguard Worker 
2850*61046927SAndroid Build Coastguard Worker     // Test if the item is disabled
2851*61046927SAndroid Build Coastguard Worker     if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
2852*61046927SAndroid Build Coastguard Worker         return false;
2853*61046927SAndroid Build Coastguard Worker 
2854*61046927SAndroid Build Coastguard Worker     // Special handling for the dummy item after Begin() which represent the title bar or tab.
2855*61046927SAndroid Build Coastguard Worker     // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
2856*61046927SAndroid Build Coastguard Worker     if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
2857*61046927SAndroid Build Coastguard Worker         return false;
2858*61046927SAndroid Build Coastguard Worker     return true;
2859*61046927SAndroid Build Coastguard Worker }
2860*61046927SAndroid Build Coastguard Worker 
2861*61046927SAndroid Build Coastguard Worker // Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
ItemHoverable(const ImRect & bb,ImGuiID id)2862*61046927SAndroid Build Coastguard Worker bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
2863*61046927SAndroid Build Coastguard Worker {
2864*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2865*61046927SAndroid Build Coastguard Worker     if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
2866*61046927SAndroid Build Coastguard Worker         return false;
2867*61046927SAndroid Build Coastguard Worker 
2868*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2869*61046927SAndroid Build Coastguard Worker     if (g.HoveredWindow != window)
2870*61046927SAndroid Build Coastguard Worker         return false;
2871*61046927SAndroid Build Coastguard Worker     if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
2872*61046927SAndroid Build Coastguard Worker         return false;
2873*61046927SAndroid Build Coastguard Worker     if (!IsMouseHoveringRect(bb.Min, bb.Max))
2874*61046927SAndroid Build Coastguard Worker         return false;
2875*61046927SAndroid Build Coastguard Worker     if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
2876*61046927SAndroid Build Coastguard Worker         return false;
2877*61046927SAndroid Build Coastguard Worker     if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
2878*61046927SAndroid Build Coastguard Worker         return false;
2879*61046927SAndroid Build Coastguard Worker 
2880*61046927SAndroid Build Coastguard Worker     SetHoveredID(id);
2881*61046927SAndroid Build Coastguard Worker     return true;
2882*61046927SAndroid Build Coastguard Worker }
2883*61046927SAndroid Build Coastguard Worker 
IsClippedEx(const ImRect & bb,ImGuiID id,bool clip_even_when_logged)2884*61046927SAndroid Build Coastguard Worker bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
2885*61046927SAndroid Build Coastguard Worker {
2886*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2887*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
2888*61046927SAndroid Build Coastguard Worker     if (!bb.Overlaps(window->ClipRect))
2889*61046927SAndroid Build Coastguard Worker         if (id == 0 || id != g.ActiveId)
2890*61046927SAndroid Build Coastguard Worker             if (clip_even_when_logged || !g.LogEnabled)
2891*61046927SAndroid Build Coastguard Worker                 return true;
2892*61046927SAndroid Build Coastguard Worker     return false;
2893*61046927SAndroid Build Coastguard Worker }
2894*61046927SAndroid Build Coastguard Worker 
FocusableItemRegister(ImGuiWindow * window,ImGuiID id,bool tab_stop)2895*61046927SAndroid Build Coastguard Worker bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
2896*61046927SAndroid Build Coastguard Worker {
2897*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2898*61046927SAndroid Build Coastguard Worker 
2899*61046927SAndroid Build Coastguard Worker     const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
2900*61046927SAndroid Build Coastguard Worker     window->FocusIdxAllCounter++;
2901*61046927SAndroid Build Coastguard Worker     if (is_tab_stop)
2902*61046927SAndroid Build Coastguard Worker         window->FocusIdxTabCounter++;
2903*61046927SAndroid Build Coastguard Worker 
2904*61046927SAndroid Build Coastguard Worker     // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
2905*61046927SAndroid Build Coastguard Worker     // Note that we can always TAB out of a widget that doesn't allow tabbing in.
2906*61046927SAndroid Build Coastguard Worker     if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
2907*61046927SAndroid Build Coastguard Worker         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.
2908*61046927SAndroid Build Coastguard Worker 
2909*61046927SAndroid Build Coastguard Worker     if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
2910*61046927SAndroid Build Coastguard Worker         return true;
2911*61046927SAndroid Build Coastguard Worker     if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
2912*61046927SAndroid Build Coastguard Worker     {
2913*61046927SAndroid Build Coastguard Worker         g.NavJustTabbedId = id;
2914*61046927SAndroid Build Coastguard Worker         return true;
2915*61046927SAndroid Build Coastguard Worker     }
2916*61046927SAndroid Build Coastguard Worker 
2917*61046927SAndroid Build Coastguard Worker     return false;
2918*61046927SAndroid Build Coastguard Worker }
2919*61046927SAndroid Build Coastguard Worker 
FocusableItemUnregister(ImGuiWindow * window)2920*61046927SAndroid Build Coastguard Worker void ImGui::FocusableItemUnregister(ImGuiWindow* window)
2921*61046927SAndroid Build Coastguard Worker {
2922*61046927SAndroid Build Coastguard Worker     window->FocusIdxAllCounter--;
2923*61046927SAndroid Build Coastguard Worker     window->FocusIdxTabCounter--;
2924*61046927SAndroid Build Coastguard Worker }
2925*61046927SAndroid Build Coastguard Worker 
CalcItemSize(ImVec2 size,float default_x,float default_y)2926*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
2927*61046927SAndroid Build Coastguard Worker {
2928*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
2929*61046927SAndroid Build Coastguard Worker     ImVec2 content_max;
2930*61046927SAndroid Build Coastguard Worker     if (size.x < 0.0f || size.y < 0.0f)
2931*61046927SAndroid Build Coastguard Worker         content_max = g.CurrentWindow->Pos + GetContentRegionMax();
2932*61046927SAndroid Build Coastguard Worker     if (size.x <= 0.0f)
2933*61046927SAndroid Build Coastguard Worker         size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
2934*61046927SAndroid Build Coastguard Worker     if (size.y <= 0.0f)
2935*61046927SAndroid Build Coastguard Worker         size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
2936*61046927SAndroid Build Coastguard Worker     return size;
2937*61046927SAndroid Build Coastguard Worker }
2938*61046927SAndroid Build Coastguard Worker 
CalcWrapWidthForPos(const ImVec2 & pos,float wrap_pos_x)2939*61046927SAndroid Build Coastguard Worker float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
2940*61046927SAndroid Build Coastguard Worker {
2941*61046927SAndroid Build Coastguard Worker     if (wrap_pos_x < 0.0f)
2942*61046927SAndroid Build Coastguard Worker         return 0.0f;
2943*61046927SAndroid Build Coastguard Worker 
2944*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
2945*61046927SAndroid Build Coastguard Worker     if (wrap_pos_x == 0.0f)
2946*61046927SAndroid Build Coastguard Worker         wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
2947*61046927SAndroid Build Coastguard Worker     else if (wrap_pos_x > 0.0f)
2948*61046927SAndroid Build Coastguard Worker         wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
2949*61046927SAndroid Build Coastguard Worker 
2950*61046927SAndroid Build Coastguard Worker     return ImMax(wrap_pos_x - pos.x, 1.0f);
2951*61046927SAndroid Build Coastguard Worker }
2952*61046927SAndroid Build Coastguard Worker 
MemAlloc(size_t size)2953*61046927SAndroid Build Coastguard Worker void* ImGui::MemAlloc(size_t size)
2954*61046927SAndroid Build Coastguard Worker {
2955*61046927SAndroid Build Coastguard Worker     if (ImGuiContext* ctx = GImGui)
2956*61046927SAndroid Build Coastguard Worker         ctx->IO.MetricsActiveAllocations++;
2957*61046927SAndroid Build Coastguard Worker     return GImAllocatorAllocFunc(size, GImAllocatorUserData);
2958*61046927SAndroid Build Coastguard Worker }
2959*61046927SAndroid Build Coastguard Worker 
MemFree(void * ptr)2960*61046927SAndroid Build Coastguard Worker void ImGui::MemFree(void* ptr)
2961*61046927SAndroid Build Coastguard Worker {
2962*61046927SAndroid Build Coastguard Worker     if (ptr)
2963*61046927SAndroid Build Coastguard Worker         if (ImGuiContext* ctx = GImGui)
2964*61046927SAndroid Build Coastguard Worker             ctx->IO.MetricsActiveAllocations--;
2965*61046927SAndroid Build Coastguard Worker     return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
2966*61046927SAndroid Build Coastguard Worker }
2967*61046927SAndroid Build Coastguard Worker 
GetClipboardText()2968*61046927SAndroid Build Coastguard Worker const char* ImGui::GetClipboardText()
2969*61046927SAndroid Build Coastguard Worker {
2970*61046927SAndroid Build Coastguard Worker     return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
2971*61046927SAndroid Build Coastguard Worker }
2972*61046927SAndroid Build Coastguard Worker 
SetClipboardText(const char * text)2973*61046927SAndroid Build Coastguard Worker void ImGui::SetClipboardText(const char* text)
2974*61046927SAndroid Build Coastguard Worker {
2975*61046927SAndroid Build Coastguard Worker     if (GImGui->IO.SetClipboardTextFn)
2976*61046927SAndroid Build Coastguard Worker         GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
2977*61046927SAndroid Build Coastguard Worker }
2978*61046927SAndroid Build Coastguard Worker 
GetVersion()2979*61046927SAndroid Build Coastguard Worker const char* ImGui::GetVersion()
2980*61046927SAndroid Build Coastguard Worker {
2981*61046927SAndroid Build Coastguard Worker     return IMGUI_VERSION;
2982*61046927SAndroid Build Coastguard Worker }
2983*61046927SAndroid Build Coastguard Worker 
2984*61046927SAndroid Build Coastguard Worker // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
2985*61046927SAndroid Build Coastguard Worker // 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
GetCurrentContext()2986*61046927SAndroid Build Coastguard Worker ImGuiContext* ImGui::GetCurrentContext()
2987*61046927SAndroid Build Coastguard Worker {
2988*61046927SAndroid Build Coastguard Worker     return GImGui;
2989*61046927SAndroid Build Coastguard Worker }
2990*61046927SAndroid Build Coastguard Worker 
SetCurrentContext(ImGuiContext * ctx)2991*61046927SAndroid Build Coastguard Worker void ImGui::SetCurrentContext(ImGuiContext* ctx)
2992*61046927SAndroid Build Coastguard Worker {
2993*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
2994*61046927SAndroid Build Coastguard Worker     IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
2995*61046927SAndroid Build Coastguard Worker #else
2996*61046927SAndroid Build Coastguard Worker     GImGui = ctx;
2997*61046927SAndroid Build Coastguard Worker #endif
2998*61046927SAndroid Build Coastguard Worker }
2999*61046927SAndroid Build Coastguard Worker 
3000*61046927SAndroid Build Coastguard Worker // Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
3001*61046927SAndroid Build Coastguard Worker // 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.
DebugCheckVersionAndDataLayout(const char * version,size_t sz_io,size_t sz_style,size_t sz_vec2,size_t sz_vec4,size_t sz_vert)3002*61046927SAndroid Build Coastguard Worker 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)
3003*61046927SAndroid Build Coastguard Worker {
3004*61046927SAndroid Build Coastguard Worker     bool error = false;
3005*61046927SAndroid Build Coastguard Worker     if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatched version string!");  }
3006*61046927SAndroid Build Coastguard Worker     if (sz_io    != sizeof(ImGuiIO))       { error = true; IM_ASSERT(sz_io    == sizeof(ImGuiIO)      && "Mismatched struct layout!"); }
3007*61046927SAndroid Build Coastguard Worker     if (sz_style != sizeof(ImGuiStyle))    { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle)   && "Mismatched struct layout!"); }
3008*61046927SAndroid Build Coastguard Worker     if (sz_vec2  != sizeof(ImVec2))        { error = true; IM_ASSERT(sz_vec2  == sizeof(ImVec2)       && "Mismatched struct layout!"); }
3009*61046927SAndroid Build Coastguard Worker     if (sz_vec4  != sizeof(ImVec4))        { error = true; IM_ASSERT(sz_vec4  == sizeof(ImVec4)       && "Mismatched struct layout!"); }
3010*61046927SAndroid Build Coastguard Worker     if (sz_vert  != sizeof(ImDrawVert))    { error = true; IM_ASSERT(sz_vert  == sizeof(ImDrawVert)   && "Mismatched struct layout!"); }
3011*61046927SAndroid Build Coastguard Worker     return !error;
3012*61046927SAndroid Build Coastguard Worker }
3013*61046927SAndroid Build Coastguard Worker 
SetAllocatorFunctions(void * (* alloc_func)(size_t sz,void * user_data),void (* free_func)(void * ptr,void * user_data),void * user_data)3014*61046927SAndroid Build Coastguard Worker void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
3015*61046927SAndroid Build Coastguard Worker {
3016*61046927SAndroid Build Coastguard Worker     GImAllocatorAllocFunc = alloc_func;
3017*61046927SAndroid Build Coastguard Worker     GImAllocatorFreeFunc = free_func;
3018*61046927SAndroid Build Coastguard Worker     GImAllocatorUserData = user_data;
3019*61046927SAndroid Build Coastguard Worker }
3020*61046927SAndroid Build Coastguard Worker 
CreateContext(ImFontAtlas * shared_font_atlas)3021*61046927SAndroid Build Coastguard Worker ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
3022*61046927SAndroid Build Coastguard Worker {
3023*61046927SAndroid Build Coastguard Worker     ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
3024*61046927SAndroid Build Coastguard Worker     if (GImGui == NULL)
3025*61046927SAndroid Build Coastguard Worker         SetCurrentContext(ctx);
3026*61046927SAndroid Build Coastguard Worker     Initialize(ctx);
3027*61046927SAndroid Build Coastguard Worker     return ctx;
3028*61046927SAndroid Build Coastguard Worker }
3029*61046927SAndroid Build Coastguard Worker 
DestroyContext(ImGuiContext * ctx)3030*61046927SAndroid Build Coastguard Worker void ImGui::DestroyContext(ImGuiContext* ctx)
3031*61046927SAndroid Build Coastguard Worker {
3032*61046927SAndroid Build Coastguard Worker     if (ctx == NULL)
3033*61046927SAndroid Build Coastguard Worker         ctx = GImGui;
3034*61046927SAndroid Build Coastguard Worker     Shutdown(ctx);
3035*61046927SAndroid Build Coastguard Worker     if (GImGui == ctx)
3036*61046927SAndroid Build Coastguard Worker         SetCurrentContext(NULL);
3037*61046927SAndroid Build Coastguard Worker     IM_DELETE(ctx);
3038*61046927SAndroid Build Coastguard Worker }
3039*61046927SAndroid Build Coastguard Worker 
GetIO()3040*61046927SAndroid Build Coastguard Worker ImGuiIO& ImGui::GetIO()
3041*61046927SAndroid Build Coastguard Worker {
3042*61046927SAndroid Build Coastguard Worker     IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
3043*61046927SAndroid Build Coastguard Worker     return GImGui->IO;
3044*61046927SAndroid Build Coastguard Worker }
3045*61046927SAndroid Build Coastguard Worker 
GetStyle()3046*61046927SAndroid Build Coastguard Worker ImGuiStyle& ImGui::GetStyle()
3047*61046927SAndroid Build Coastguard Worker {
3048*61046927SAndroid Build Coastguard Worker     IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
3049*61046927SAndroid Build Coastguard Worker     return GImGui->Style;
3050*61046927SAndroid Build Coastguard Worker }
3051*61046927SAndroid Build Coastguard Worker 
3052*61046927SAndroid Build Coastguard Worker // Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame()
GetDrawData()3053*61046927SAndroid Build Coastguard Worker ImDrawData* ImGui::GetDrawData()
3054*61046927SAndroid Build Coastguard Worker {
3055*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3056*61046927SAndroid Build Coastguard Worker     return g.DrawData.Valid ? &g.DrawData : NULL;
3057*61046927SAndroid Build Coastguard Worker }
3058*61046927SAndroid Build Coastguard Worker 
GetTime()3059*61046927SAndroid Build Coastguard Worker double ImGui::GetTime()
3060*61046927SAndroid Build Coastguard Worker {
3061*61046927SAndroid Build Coastguard Worker     return GImGui->Time;
3062*61046927SAndroid Build Coastguard Worker }
3063*61046927SAndroid Build Coastguard Worker 
GetFrameCount()3064*61046927SAndroid Build Coastguard Worker int ImGui::GetFrameCount()
3065*61046927SAndroid Build Coastguard Worker {
3066*61046927SAndroid Build Coastguard Worker     return GImGui->FrameCount;
3067*61046927SAndroid Build Coastguard Worker }
3068*61046927SAndroid Build Coastguard Worker 
GetOverlayDrawList(ImGuiWindow *)3069*61046927SAndroid Build Coastguard Worker static ImDrawList* GetOverlayDrawList(ImGuiWindow*)
3070*61046927SAndroid Build Coastguard Worker {
3071*61046927SAndroid Build Coastguard Worker     // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'viewport' branches.
3072*61046927SAndroid Build Coastguard Worker     return &GImGui->OverlayDrawList;
3073*61046927SAndroid Build Coastguard Worker }
3074*61046927SAndroid Build Coastguard Worker 
GetOverlayDrawList()3075*61046927SAndroid Build Coastguard Worker ImDrawList* ImGui::GetOverlayDrawList()
3076*61046927SAndroid Build Coastguard Worker {
3077*61046927SAndroid Build Coastguard Worker     return &GImGui->OverlayDrawList;
3078*61046927SAndroid Build Coastguard Worker }
3079*61046927SAndroid Build Coastguard Worker 
GetDrawListSharedData()3080*61046927SAndroid Build Coastguard Worker ImDrawListSharedData* ImGui::GetDrawListSharedData()
3081*61046927SAndroid Build Coastguard Worker {
3082*61046927SAndroid Build Coastguard Worker     return &GImGui->DrawListSharedData;
3083*61046927SAndroid Build Coastguard Worker }
3084*61046927SAndroid Build Coastguard Worker 
StartMouseMovingWindow(ImGuiWindow * window)3085*61046927SAndroid Build Coastguard Worker void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
3086*61046927SAndroid Build Coastguard Worker {
3087*61046927SAndroid Build Coastguard Worker     // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
3088*61046927SAndroid Build Coastguard Worker     // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
3089*61046927SAndroid Build Coastguard Worker     // This is because we want ActiveId to be set even when the window is not permitted to move.
3090*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3091*61046927SAndroid Build Coastguard Worker     FocusWindow(window);
3092*61046927SAndroid Build Coastguard Worker     SetActiveID(window->MoveId, window);
3093*61046927SAndroid Build Coastguard Worker     g.NavDisableHighlight = true;
3094*61046927SAndroid Build Coastguard Worker     g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
3095*61046927SAndroid Build Coastguard Worker 
3096*61046927SAndroid Build Coastguard Worker     bool can_move_window = true;
3097*61046927SAndroid Build Coastguard Worker     if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
3098*61046927SAndroid Build Coastguard Worker         can_move_window = false;
3099*61046927SAndroid Build Coastguard Worker     if (can_move_window)
3100*61046927SAndroid Build Coastguard Worker         g.MovingWindow = window;
3101*61046927SAndroid Build Coastguard Worker }
3102*61046927SAndroid Build Coastguard Worker 
3103*61046927SAndroid Build Coastguard Worker // Handle mouse moving window
3104*61046927SAndroid Build Coastguard Worker // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
UpdateMouseMovingWindowNewFrame()3105*61046927SAndroid Build Coastguard Worker void ImGui::UpdateMouseMovingWindowNewFrame()
3106*61046927SAndroid Build Coastguard Worker {
3107*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3108*61046927SAndroid Build Coastguard Worker     if (g.MovingWindow != NULL)
3109*61046927SAndroid Build Coastguard Worker     {
3110*61046927SAndroid Build Coastguard Worker         // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
3111*61046927SAndroid Build Coastguard Worker         // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
3112*61046927SAndroid Build Coastguard Worker         KeepAliveID(g.ActiveId);
3113*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
3114*61046927SAndroid Build Coastguard Worker         ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
3115*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
3116*61046927SAndroid Build Coastguard Worker         {
3117*61046927SAndroid Build Coastguard Worker             ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
3118*61046927SAndroid Build Coastguard Worker             if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
3119*61046927SAndroid Build Coastguard Worker             {
3120*61046927SAndroid Build Coastguard Worker                 MarkIniSettingsDirty(moving_window);
3121*61046927SAndroid Build Coastguard Worker                 SetWindowPos(moving_window, pos, ImGuiCond_Always);
3122*61046927SAndroid Build Coastguard Worker             }
3123*61046927SAndroid Build Coastguard Worker             FocusWindow(g.MovingWindow);
3124*61046927SAndroid Build Coastguard Worker         }
3125*61046927SAndroid Build Coastguard Worker         else
3126*61046927SAndroid Build Coastguard Worker         {
3127*61046927SAndroid Build Coastguard Worker             ClearActiveID();
3128*61046927SAndroid Build Coastguard Worker             g.MovingWindow = NULL;
3129*61046927SAndroid Build Coastguard Worker         }
3130*61046927SAndroid Build Coastguard Worker     }
3131*61046927SAndroid Build Coastguard Worker     else
3132*61046927SAndroid Build Coastguard Worker     {
3133*61046927SAndroid Build Coastguard Worker         // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
3134*61046927SAndroid Build Coastguard Worker         if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
3135*61046927SAndroid Build Coastguard Worker         {
3136*61046927SAndroid Build Coastguard Worker             KeepAliveID(g.ActiveId);
3137*61046927SAndroid Build Coastguard Worker             if (!g.IO.MouseDown[0])
3138*61046927SAndroid Build Coastguard Worker                 ClearActiveID();
3139*61046927SAndroid Build Coastguard Worker         }
3140*61046927SAndroid Build Coastguard Worker     }
3141*61046927SAndroid Build Coastguard Worker }
3142*61046927SAndroid Build Coastguard Worker 
3143*61046927SAndroid Build Coastguard Worker // Initiate moving window, handle left-click and right-click focus
UpdateMouseMovingWindowEndFrame()3144*61046927SAndroid Build Coastguard Worker void ImGui::UpdateMouseMovingWindowEndFrame()
3145*61046927SAndroid Build Coastguard Worker {
3146*61046927SAndroid Build Coastguard Worker     // Initiate moving window
3147*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3148*61046927SAndroid Build Coastguard Worker     if (g.ActiveId != 0 || g.HoveredId != 0)
3149*61046927SAndroid Build Coastguard Worker         return;
3150*61046927SAndroid Build Coastguard Worker 
3151*61046927SAndroid Build Coastguard Worker     // Unless we just made a window/popup appear
3152*61046927SAndroid Build Coastguard Worker     if (g.NavWindow && g.NavWindow->Appearing)
3153*61046927SAndroid Build Coastguard Worker         return;
3154*61046927SAndroid Build Coastguard Worker 
3155*61046927SAndroid Build Coastguard Worker     // Click to focus window and start moving (after we're done with all our widgets)
3156*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseClicked[0])
3157*61046927SAndroid Build Coastguard Worker     {
3158*61046927SAndroid Build Coastguard Worker         if (g.HoveredRootWindow != NULL)
3159*61046927SAndroid Build Coastguard Worker         {
3160*61046927SAndroid Build Coastguard Worker             StartMouseMovingWindow(g.HoveredWindow);
3161*61046927SAndroid Build Coastguard Worker             if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoTitleBar))
3162*61046927SAndroid Build Coastguard Worker                 if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
3163*61046927SAndroid Build Coastguard Worker                     g.MovingWindow = NULL;
3164*61046927SAndroid Build Coastguard Worker         }
3165*61046927SAndroid Build Coastguard Worker         else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL)
3166*61046927SAndroid Build Coastguard Worker         {
3167*61046927SAndroid Build Coastguard Worker             // Clicking on void disable focus
3168*61046927SAndroid Build Coastguard Worker             FocusWindow(NULL);
3169*61046927SAndroid Build Coastguard Worker         }
3170*61046927SAndroid Build Coastguard Worker     }
3171*61046927SAndroid Build Coastguard Worker 
3172*61046927SAndroid Build Coastguard Worker     // With right mouse button we close popups without changing focus
3173*61046927SAndroid Build Coastguard Worker     // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger)
3174*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseClicked[1])
3175*61046927SAndroid Build Coastguard Worker     {
3176*61046927SAndroid Build Coastguard Worker         // Find the top-most window between HoveredWindow and the front most Modal Window.
3177*61046927SAndroid Build Coastguard Worker         // This is where we can trim the popup stack.
3178*61046927SAndroid Build Coastguard Worker         ImGuiWindow* modal = GetFrontMostPopupModal();
3179*61046927SAndroid Build Coastguard Worker         bool hovered_window_above_modal = false;
3180*61046927SAndroid Build Coastguard Worker         if (modal == NULL)
3181*61046927SAndroid Build Coastguard Worker             hovered_window_above_modal = true;
3182*61046927SAndroid Build Coastguard Worker         for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--)
3183*61046927SAndroid Build Coastguard Worker         {
3184*61046927SAndroid Build Coastguard Worker             ImGuiWindow* window = g.Windows[i];
3185*61046927SAndroid Build Coastguard Worker             if (window == modal)
3186*61046927SAndroid Build Coastguard Worker                 break;
3187*61046927SAndroid Build Coastguard Worker             if (window == g.HoveredWindow)
3188*61046927SAndroid Build Coastguard Worker                 hovered_window_above_modal = true;
3189*61046927SAndroid Build Coastguard Worker         }
3190*61046927SAndroid Build Coastguard Worker         ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal);
3191*61046927SAndroid Build Coastguard Worker     }
3192*61046927SAndroid Build Coastguard Worker }
3193*61046927SAndroid Build Coastguard Worker 
IsWindowActiveAndVisible(ImGuiWindow * window)3194*61046927SAndroid Build Coastguard Worker static bool IsWindowActiveAndVisible(ImGuiWindow* window)
3195*61046927SAndroid Build Coastguard Worker {
3196*61046927SAndroid Build Coastguard Worker     return (window->Active) && (!window->Hidden);
3197*61046927SAndroid Build Coastguard Worker }
3198*61046927SAndroid Build Coastguard Worker 
UpdateMouseInputs()3199*61046927SAndroid Build Coastguard Worker static void ImGui::UpdateMouseInputs()
3200*61046927SAndroid Build Coastguard Worker {
3201*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3202*61046927SAndroid Build Coastguard Worker 
3203*61046927SAndroid Build Coastguard Worker     // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
3204*61046927SAndroid Build Coastguard Worker     if (IsMousePosValid(&g.IO.MousePos))
3205*61046927SAndroid Build Coastguard Worker         g.IO.MousePos = g.LastValidMousePos = ImFloor(g.IO.MousePos);
3206*61046927SAndroid Build Coastguard Worker 
3207*61046927SAndroid Build Coastguard Worker     // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
3208*61046927SAndroid Build Coastguard Worker     if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))
3209*61046927SAndroid Build Coastguard Worker         g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
3210*61046927SAndroid Build Coastguard Worker     else
3211*61046927SAndroid Build Coastguard Worker         g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
3212*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)
3213*61046927SAndroid Build Coastguard Worker         g.NavDisableMouseHover = false;
3214*61046927SAndroid Build Coastguard Worker 
3215*61046927SAndroid Build Coastguard Worker     g.IO.MousePosPrev = g.IO.MousePos;
3216*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
3217*61046927SAndroid Build Coastguard Worker     {
3218*61046927SAndroid Build Coastguard Worker         g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
3219*61046927SAndroid Build Coastguard Worker         g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
3220*61046927SAndroid Build Coastguard Worker         g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
3221*61046927SAndroid Build Coastguard Worker         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;
3222*61046927SAndroid Build Coastguard Worker         g.IO.MouseDoubleClicked[i] = false;
3223*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseClicked[i])
3224*61046927SAndroid Build Coastguard Worker         {
3225*61046927SAndroid Build Coastguard Worker             if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
3226*61046927SAndroid Build Coastguard Worker             {
3227*61046927SAndroid Build Coastguard Worker                 ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
3228*61046927SAndroid Build Coastguard Worker                 if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
3229*61046927SAndroid Build Coastguard Worker                     g.IO.MouseDoubleClicked[i] = true;
3230*61046927SAndroid Build Coastguard Worker                 g.IO.MouseClickedTime[i] = -FLT_MAX;    // so the third click isn't turned into a double-click
3231*61046927SAndroid Build Coastguard Worker             }
3232*61046927SAndroid Build Coastguard Worker             else
3233*61046927SAndroid Build Coastguard Worker             {
3234*61046927SAndroid Build Coastguard Worker                 g.IO.MouseClickedTime[i] = g.Time;
3235*61046927SAndroid Build Coastguard Worker             }
3236*61046927SAndroid Build Coastguard Worker             g.IO.MouseClickedPos[i] = g.IO.MousePos;
3237*61046927SAndroid Build Coastguard Worker             g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
3238*61046927SAndroid Build Coastguard Worker             g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
3239*61046927SAndroid Build Coastguard Worker         }
3240*61046927SAndroid Build Coastguard Worker         else if (g.IO.MouseDown[i])
3241*61046927SAndroid Build Coastguard Worker         {
3242*61046927SAndroid Build Coastguard Worker             // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
3243*61046927SAndroid Build Coastguard Worker             ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
3244*61046927SAndroid Build Coastguard Worker             g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
3245*61046927SAndroid Build Coastguard Worker             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);
3246*61046927SAndroid Build Coastguard Worker             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);
3247*61046927SAndroid Build Coastguard Worker         }
3248*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
3249*61046927SAndroid Build Coastguard Worker             g.NavDisableMouseHover = false;
3250*61046927SAndroid Build Coastguard Worker     }
3251*61046927SAndroid Build Coastguard Worker }
3252*61046927SAndroid Build Coastguard Worker 
UpdateMouseWheel()3253*61046927SAndroid Build Coastguard Worker void ImGui::UpdateMouseWheel()
3254*61046927SAndroid Build Coastguard Worker {
3255*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3256*61046927SAndroid Build Coastguard Worker     if (!g.HoveredWindow || g.HoveredWindow->Collapsed)
3257*61046927SAndroid Build Coastguard Worker         return;
3258*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
3259*61046927SAndroid Build Coastguard Worker         return;
3260*61046927SAndroid Build Coastguard Worker 
3261*61046927SAndroid Build Coastguard Worker     // 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).
3262*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.HoveredWindow;
3263*61046927SAndroid Build Coastguard Worker     ImGuiWindow* scroll_window = window;
3264*61046927SAndroid Build Coastguard Worker     while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs) && scroll_window->ParentWindow)
3265*61046927SAndroid Build Coastguard Worker         scroll_window = scroll_window->ParentWindow;
3266*61046927SAndroid Build Coastguard Worker     const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs);
3267*61046927SAndroid Build Coastguard Worker 
3268*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseWheel != 0.0f)
3269*61046927SAndroid Build Coastguard Worker     {
3270*61046927SAndroid Build Coastguard Worker         if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
3271*61046927SAndroid Build Coastguard Worker         {
3272*61046927SAndroid Build Coastguard Worker             // Zoom / Scale window
3273*61046927SAndroid Build Coastguard Worker             const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
3274*61046927SAndroid Build Coastguard Worker             const float scale = new_font_scale / window->FontWindowScale;
3275*61046927SAndroid Build Coastguard Worker             window->FontWindowScale = new_font_scale;
3276*61046927SAndroid Build Coastguard Worker 
3277*61046927SAndroid Build Coastguard Worker             const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
3278*61046927SAndroid Build Coastguard Worker             window->Pos += offset;
3279*61046927SAndroid Build Coastguard Worker             window->Size *= scale;
3280*61046927SAndroid Build Coastguard Worker             window->SizeFull *= scale;
3281*61046927SAndroid Build Coastguard Worker         }
3282*61046927SAndroid Build Coastguard Worker         else if (!g.IO.KeyCtrl && scroll_allowed)
3283*61046927SAndroid Build Coastguard Worker         {
3284*61046927SAndroid Build Coastguard Worker             // Mouse wheel vertical scrolling
3285*61046927SAndroid Build Coastguard Worker             float scroll_amount = 5 * scroll_window->CalcFontSize();
3286*61046927SAndroid Build Coastguard Worker             scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f);
3287*61046927SAndroid Build Coastguard Worker             SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount);
3288*61046927SAndroid Build Coastguard Worker         }
3289*61046927SAndroid Build Coastguard Worker     }
3290*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseWheelH != 0.0f && scroll_allowed && !g.IO.KeyCtrl)
3291*61046927SAndroid Build Coastguard Worker     {
3292*61046927SAndroid Build Coastguard Worker         // Mouse wheel horizontal scrolling (for hardware that supports it)
3293*61046927SAndroid Build Coastguard Worker         float scroll_amount = scroll_window->CalcFontSize();
3294*61046927SAndroid Build Coastguard Worker         SetWindowScrollX(scroll_window, scroll_window->Scroll.x - g.IO.MouseWheelH * scroll_amount);
3295*61046927SAndroid Build Coastguard Worker     }
3296*61046927SAndroid Build Coastguard Worker }
3297*61046927SAndroid Build Coastguard Worker 
3298*61046927SAndroid Build Coastguard Worker // 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)
UpdateHoveredWindowAndCaptureFlags()3299*61046927SAndroid Build Coastguard Worker void ImGui::UpdateHoveredWindowAndCaptureFlags()
3300*61046927SAndroid Build Coastguard Worker {
3301*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3302*61046927SAndroid Build Coastguard Worker 
3303*61046927SAndroid Build Coastguard Worker     // Find the window hovered by mouse:
3304*61046927SAndroid Build Coastguard Worker     // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
3305*61046927SAndroid Build Coastguard Worker     // - 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.
3306*61046927SAndroid Build Coastguard Worker     // - 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.
3307*61046927SAndroid Build Coastguard Worker     FindHoveredWindow();
3308*61046927SAndroid Build Coastguard Worker 
3309*61046927SAndroid Build Coastguard Worker     // Modal windows prevents cursor from hovering behind them.
3310*61046927SAndroid Build Coastguard Worker     ImGuiWindow* modal_window = GetFrontMostPopupModal();
3311*61046927SAndroid Build Coastguard Worker     if (modal_window)
3312*61046927SAndroid Build Coastguard Worker         if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
3313*61046927SAndroid Build Coastguard Worker             g.HoveredRootWindow = g.HoveredWindow = NULL;
3314*61046927SAndroid Build Coastguard Worker 
3315*61046927SAndroid Build Coastguard Worker     // Disabled mouse?
3316*61046927SAndroid Build Coastguard Worker     if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse)
3317*61046927SAndroid Build Coastguard Worker         g.HoveredWindow = g.HoveredRootWindow = NULL;
3318*61046927SAndroid Build Coastguard Worker 
3319*61046927SAndroid Build Coastguard Worker     // 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.
3320*61046927SAndroid Build Coastguard Worker     int mouse_earliest_button_down = -1;
3321*61046927SAndroid Build Coastguard Worker     bool mouse_any_down = false;
3322*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
3323*61046927SAndroid Build Coastguard Worker     {
3324*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseClicked[i])
3325*61046927SAndroid Build Coastguard Worker             g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
3326*61046927SAndroid Build Coastguard Worker         mouse_any_down |= g.IO.MouseDown[i];
3327*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseDown[i])
3328*61046927SAndroid Build Coastguard Worker             if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
3329*61046927SAndroid Build Coastguard Worker                 mouse_earliest_button_down = i;
3330*61046927SAndroid Build Coastguard Worker     }
3331*61046927SAndroid Build Coastguard Worker     const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
3332*61046927SAndroid Build Coastguard Worker 
3333*61046927SAndroid Build Coastguard Worker     // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
3334*61046927SAndroid Build Coastguard Worker     // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
3335*61046927SAndroid Build Coastguard Worker     const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
3336*61046927SAndroid Build Coastguard Worker     if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
3337*61046927SAndroid Build Coastguard Worker         g.HoveredWindow = g.HoveredRootWindow = NULL;
3338*61046927SAndroid Build Coastguard Worker 
3339*61046927SAndroid Build Coastguard Worker     // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app)
3340*61046927SAndroid Build Coastguard Worker     if (g.WantCaptureMouseNextFrame != -1)
3341*61046927SAndroid Build Coastguard Worker         g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
3342*61046927SAndroid Build Coastguard Worker     else
3343*61046927SAndroid Build Coastguard Worker         g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
3344*61046927SAndroid Build Coastguard Worker 
3345*61046927SAndroid Build Coastguard Worker     // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app)
3346*61046927SAndroid Build Coastguard Worker     if (g.WantCaptureKeyboardNextFrame != -1)
3347*61046927SAndroid Build Coastguard Worker         g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
3348*61046927SAndroid Build Coastguard Worker     else
3349*61046927SAndroid Build Coastguard Worker         g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
3350*61046927SAndroid Build Coastguard Worker     if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
3351*61046927SAndroid Build Coastguard Worker         g.IO.WantCaptureKeyboard = true;
3352*61046927SAndroid Build Coastguard Worker 
3353*61046927SAndroid Build Coastguard Worker     // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible
3354*61046927SAndroid Build Coastguard Worker     g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
3355*61046927SAndroid Build Coastguard Worker }
3356*61046927SAndroid Build Coastguard Worker 
NewFrame()3357*61046927SAndroid Build Coastguard Worker void ImGui::NewFrame()
3358*61046927SAndroid Build Coastguard Worker {
3359*61046927SAndroid Build Coastguard Worker     IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
3360*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3361*61046927SAndroid Build Coastguard Worker 
3362*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_ENABLE_TEST_ENGINE
3363*61046927SAndroid Build Coastguard Worker     ImGuiTestEngineHook_PreNewFrame(&g);
3364*61046927SAndroid Build Coastguard Worker #endif
3365*61046927SAndroid Build Coastguard Worker 
3366*61046927SAndroid Build Coastguard Worker     // Check user data
3367*61046927SAndroid Build Coastguard Worker     // (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)
3368*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Initialized);
3369*61046927SAndroid Build Coastguard Worker     IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0)              && "Need a positive DeltaTime!");
3370*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f  && "Invalid DisplaySize value!");
3371*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.IO.Fonts->Fonts.Size > 0                                && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
3372*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()                          && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
3373*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Style.CurveTessellationTol > 0.0f                       && "Invalid style setting!");
3374*61046927SAndroid Build Coastguard Worker     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)!");
3375*61046927SAndroid Build Coastguard Worker     IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount)  && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
3376*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < ImGuiKey_COUNT; n++)
3377*61046927SAndroid Build Coastguard Worker         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)");
3378*61046927SAndroid Build Coastguard Worker 
3379*61046927SAndroid Build Coastguard Worker     // 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)
3380*61046927SAndroid Build Coastguard Worker     if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
3381*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
3382*61046927SAndroid Build Coastguard Worker 
3383*61046927SAndroid Build Coastguard Worker     // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
3384*61046927SAndroid Build Coastguard Worker     if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
3385*61046927SAndroid Build Coastguard Worker         g.IO.ConfigWindowsResizeFromEdges = false;
3386*61046927SAndroid Build Coastguard Worker 
3387*61046927SAndroid Build Coastguard Worker     // Load settings on first frame (if not explicitly loaded manually before)
3388*61046927SAndroid Build Coastguard Worker     if (!g.SettingsLoaded)
3389*61046927SAndroid Build Coastguard Worker     {
3390*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.SettingsWindows.empty());
3391*61046927SAndroid Build Coastguard Worker         if (g.IO.IniFilename)
3392*61046927SAndroid Build Coastguard Worker             LoadIniSettingsFromDisk(g.IO.IniFilename);
3393*61046927SAndroid Build Coastguard Worker         g.SettingsLoaded = true;
3394*61046927SAndroid Build Coastguard Worker     }
3395*61046927SAndroid Build Coastguard Worker 
3396*61046927SAndroid Build Coastguard Worker     // Save settings (with a delay after the last modification, so we don't spam disk too much)
3397*61046927SAndroid Build Coastguard Worker     if (g.SettingsDirtyTimer > 0.0f)
3398*61046927SAndroid Build Coastguard Worker     {
3399*61046927SAndroid Build Coastguard Worker         g.SettingsDirtyTimer -= g.IO.DeltaTime;
3400*61046927SAndroid Build Coastguard Worker         if (g.SettingsDirtyTimer <= 0.0f)
3401*61046927SAndroid Build Coastguard Worker         {
3402*61046927SAndroid Build Coastguard Worker             if (g.IO.IniFilename != NULL)
3403*61046927SAndroid Build Coastguard Worker                 SaveIniSettingsToDisk(g.IO.IniFilename);
3404*61046927SAndroid Build Coastguard Worker             else
3405*61046927SAndroid Build Coastguard Worker                 g.IO.WantSaveIniSettings = true;  // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
3406*61046927SAndroid Build Coastguard Worker             g.SettingsDirtyTimer = 0.0f;
3407*61046927SAndroid Build Coastguard Worker         }
3408*61046927SAndroid Build Coastguard Worker     }
3409*61046927SAndroid Build Coastguard Worker 
3410*61046927SAndroid Build Coastguard Worker     g.Time += g.IO.DeltaTime;
3411*61046927SAndroid Build Coastguard Worker     g.FrameScopeActive = true;
3412*61046927SAndroid Build Coastguard Worker     g.FrameCount += 1;
3413*61046927SAndroid Build Coastguard Worker     g.TooltipOverrideCount = 0;
3414*61046927SAndroid Build Coastguard Worker     g.WindowsActiveCount = 0;
3415*61046927SAndroid Build Coastguard Worker 
3416*61046927SAndroid Build Coastguard Worker     // Setup current font and draw list shared data
3417*61046927SAndroid Build Coastguard Worker     g.IO.Fonts->Locked = true;
3418*61046927SAndroid Build Coastguard Worker     SetCurrentFont(GetDefaultFont());
3419*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Font->IsLoaded());
3420*61046927SAndroid Build Coastguard Worker     g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
3421*61046927SAndroid Build Coastguard Worker     g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
3422*61046927SAndroid Build Coastguard Worker 
3423*61046927SAndroid Build Coastguard Worker     g.OverlayDrawList.Clear();
3424*61046927SAndroid Build Coastguard Worker     g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID);
3425*61046927SAndroid Build Coastguard Worker     g.OverlayDrawList.PushClipRectFullScreen();
3426*61046927SAndroid Build Coastguard Worker     g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
3427*61046927SAndroid Build Coastguard Worker 
3428*61046927SAndroid Build Coastguard Worker     // Mark rendering data as invalid to prevent user who may have a handle on it to use it.
3429*61046927SAndroid Build Coastguard Worker     g.DrawData.Clear();
3430*61046927SAndroid Build Coastguard Worker 
3431*61046927SAndroid Build Coastguard Worker     // Drag and drop keep the source ID alive so even if the source disappear our state is consistent
3432*61046927SAndroid Build Coastguard Worker     if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
3433*61046927SAndroid Build Coastguard Worker         KeepAliveID(g.DragDropPayload.SourceId);
3434*61046927SAndroid Build Coastguard Worker 
3435*61046927SAndroid Build Coastguard Worker     // Clear reference to active widget if the widget isn't alive anymore
3436*61046927SAndroid Build Coastguard Worker     if (!g.HoveredIdPreviousFrame)
3437*61046927SAndroid Build Coastguard Worker         g.HoveredIdTimer = 0.0f;
3438*61046927SAndroid Build Coastguard Worker     if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
3439*61046927SAndroid Build Coastguard Worker         g.HoveredIdNotActiveTimer = 0.0f;
3440*61046927SAndroid Build Coastguard Worker     if (g.HoveredId)
3441*61046927SAndroid Build Coastguard Worker         g.HoveredIdTimer += g.IO.DeltaTime;
3442*61046927SAndroid Build Coastguard Worker     if (g.HoveredId && g.ActiveId != g.HoveredId)
3443*61046927SAndroid Build Coastguard Worker         g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
3444*61046927SAndroid Build Coastguard Worker     g.HoveredIdPreviousFrame = g.HoveredId;
3445*61046927SAndroid Build Coastguard Worker     g.HoveredId = 0;
3446*61046927SAndroid Build Coastguard Worker     g.HoveredIdAllowOverlap = false;
3447*61046927SAndroid Build Coastguard Worker     if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
3448*61046927SAndroid Build Coastguard Worker         ClearActiveID();
3449*61046927SAndroid Build Coastguard Worker     if (g.ActiveId)
3450*61046927SAndroid Build Coastguard Worker         g.ActiveIdTimer += g.IO.DeltaTime;
3451*61046927SAndroid Build Coastguard Worker     g.LastActiveIdTimer += g.IO.DeltaTime;
3452*61046927SAndroid Build Coastguard Worker     g.ActiveIdPreviousFrame = g.ActiveId;
3453*61046927SAndroid Build Coastguard Worker     g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
3454*61046927SAndroid Build Coastguard Worker     g.ActiveIdPreviousFrameHasBeenEdited = g.ActiveIdHasBeenEdited;
3455*61046927SAndroid Build Coastguard Worker     g.ActiveIdIsAlive = 0;
3456*61046927SAndroid Build Coastguard Worker     g.ActiveIdPreviousFrameIsAlive = false;
3457*61046927SAndroid Build Coastguard Worker     g.ActiveIdIsJustActivated = false;
3458*61046927SAndroid Build Coastguard Worker     if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
3459*61046927SAndroid Build Coastguard Worker         g.ScalarAsInputTextId = 0;
3460*61046927SAndroid Build Coastguard Worker 
3461*61046927SAndroid Build Coastguard Worker     // Drag and drop
3462*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
3463*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptIdCurr = 0;
3464*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
3465*61046927SAndroid Build Coastguard Worker     g.DragDropWithinSourceOrTarget = false;
3466*61046927SAndroid Build Coastguard Worker 
3467*61046927SAndroid Build Coastguard Worker     // Update keyboard input state
3468*61046927SAndroid Build Coastguard Worker     memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
3469*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
3470*61046927SAndroid Build Coastguard Worker         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;
3471*61046927SAndroid Build Coastguard Worker 
3472*61046927SAndroid Build Coastguard Worker     // Update gamepad/keyboard directional navigation
3473*61046927SAndroid Build Coastguard Worker     NavUpdate();
3474*61046927SAndroid Build Coastguard Worker 
3475*61046927SAndroid Build Coastguard Worker     // Update mouse input state
3476*61046927SAndroid Build Coastguard Worker     UpdateMouseInputs();
3477*61046927SAndroid Build Coastguard Worker 
3478*61046927SAndroid Build Coastguard Worker     // Calculate frame-rate for the user, as a purely luxurious feature
3479*61046927SAndroid Build Coastguard Worker     g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
3480*61046927SAndroid Build Coastguard Worker     g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
3481*61046927SAndroid Build Coastguard Worker     g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
3482*61046927SAndroid Build Coastguard Worker     g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
3483*61046927SAndroid Build Coastguard Worker 
3484*61046927SAndroid Build Coastguard Worker     // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
3485*61046927SAndroid Build Coastguard Worker     UpdateMouseMovingWindowNewFrame();
3486*61046927SAndroid Build Coastguard Worker     UpdateHoveredWindowAndCaptureFlags();
3487*61046927SAndroid Build Coastguard Worker 
3488*61046927SAndroid Build Coastguard Worker     // Background darkening/whitening
3489*61046927SAndroid Build Coastguard Worker     if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f))
3490*61046927SAndroid Build Coastguard Worker         g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f);
3491*61046927SAndroid Build Coastguard Worker     else
3492*61046927SAndroid Build Coastguard Worker         g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f);
3493*61046927SAndroid Build Coastguard Worker 
3494*61046927SAndroid Build Coastguard Worker     g.MouseCursor = ImGuiMouseCursor_Arrow;
3495*61046927SAndroid Build Coastguard Worker     g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
3496*61046927SAndroid Build Coastguard Worker     g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
3497*61046927SAndroid Build Coastguard Worker 
3498*61046927SAndroid Build Coastguard Worker     // Mouse wheel scrolling, scale
3499*61046927SAndroid Build Coastguard Worker     UpdateMouseWheel();
3500*61046927SAndroid Build Coastguard Worker 
3501*61046927SAndroid Build Coastguard Worker     // Pressing TAB activate widget focus
3502*61046927SAndroid Build Coastguard Worker     if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false))
3503*61046927SAndroid Build Coastguard Worker     {
3504*61046927SAndroid Build Coastguard Worker         if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
3505*61046927SAndroid Build Coastguard Worker             g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
3506*61046927SAndroid Build Coastguard Worker         else
3507*61046927SAndroid Build Coastguard Worker             g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0;
3508*61046927SAndroid Build Coastguard Worker     }
3509*61046927SAndroid Build Coastguard Worker     g.NavIdTabCounter = INT_MAX;
3510*61046927SAndroid Build Coastguard Worker 
3511*61046927SAndroid Build Coastguard Worker     // Mark all windows as not visible
3512*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size);
3513*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != g.Windows.Size; i++)
3514*61046927SAndroid Build Coastguard Worker     {
3515*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.Windows[i];
3516*61046927SAndroid Build Coastguard Worker         window->WasActive = window->Active;
3517*61046927SAndroid Build Coastguard Worker         window->Active = false;
3518*61046927SAndroid Build Coastguard Worker         window->WriteAccessed = false;
3519*61046927SAndroid Build Coastguard Worker     }
3520*61046927SAndroid Build Coastguard Worker 
3521*61046927SAndroid Build Coastguard Worker     // Closing the focused window restore focus to the first active root window in descending z-order
3522*61046927SAndroid Build Coastguard Worker     if (g.NavWindow && !g.NavWindow->WasActive)
3523*61046927SAndroid Build Coastguard Worker         FocusPreviousWindowIgnoringOne(NULL);
3524*61046927SAndroid Build Coastguard Worker 
3525*61046927SAndroid Build Coastguard Worker     // No window should be open at the beginning of the frame.
3526*61046927SAndroid Build Coastguard Worker     // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
3527*61046927SAndroid Build Coastguard Worker     g.CurrentWindowStack.resize(0);
3528*61046927SAndroid Build Coastguard Worker     g.BeginPopupStack.resize(0);
3529*61046927SAndroid Build Coastguard Worker     ClosePopupsOverWindow(g.NavWindow);
3530*61046927SAndroid Build Coastguard Worker 
3531*61046927SAndroid Build Coastguard Worker     // Create implicit/fallback window - which we will only render it if the user has added something to it.
3532*61046927SAndroid Build Coastguard Worker     // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
3533*61046927SAndroid Build Coastguard Worker     // This fallback is particularly important as it avoid ImGui:: calls from crashing.
3534*61046927SAndroid Build Coastguard Worker     SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
3535*61046927SAndroid Build Coastguard Worker     Begin("Debug##Default");
3536*61046927SAndroid Build Coastguard Worker     g.FrameScopePushedImplicitWindow = true;
3537*61046927SAndroid Build Coastguard Worker 
3538*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_ENABLE_TEST_ENGINE
3539*61046927SAndroid Build Coastguard Worker     ImGuiTestEngineHook_PostNewFrame(&g);
3540*61046927SAndroid Build Coastguard Worker #endif
3541*61046927SAndroid Build Coastguard Worker }
3542*61046927SAndroid Build Coastguard Worker 
Initialize(ImGuiContext * context)3543*61046927SAndroid Build Coastguard Worker void ImGui::Initialize(ImGuiContext* context)
3544*61046927SAndroid Build Coastguard Worker {
3545*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *context;
3546*61046927SAndroid Build Coastguard Worker     IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
3547*61046927SAndroid Build Coastguard Worker 
3548*61046927SAndroid Build Coastguard Worker     // Add .ini handle for ImGuiWindow type
3549*61046927SAndroid Build Coastguard Worker     ImGuiSettingsHandler ini_handler;
3550*61046927SAndroid Build Coastguard Worker     ini_handler.TypeName = "Window";
3551*61046927SAndroid Build Coastguard Worker     ini_handler.TypeHash = ImHashStr("Window", 0);
3552*61046927SAndroid Build Coastguard Worker     ini_handler.ReadOpenFn = SettingsHandlerWindow_ReadOpen;
3553*61046927SAndroid Build Coastguard Worker     ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine;
3554*61046927SAndroid Build Coastguard Worker     ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll;
3555*61046927SAndroid Build Coastguard Worker     g.SettingsHandlers.push_back(ini_handler);
3556*61046927SAndroid Build Coastguard Worker 
3557*61046927SAndroid Build Coastguard Worker     g.Initialized = true;
3558*61046927SAndroid Build Coastguard Worker }
3559*61046927SAndroid Build Coastguard Worker 
3560*61046927SAndroid Build Coastguard Worker // This function is merely here to free heap allocations.
Shutdown(ImGuiContext * context)3561*61046927SAndroid Build Coastguard Worker void ImGui::Shutdown(ImGuiContext* context)
3562*61046927SAndroid Build Coastguard Worker {
3563*61046927SAndroid Build Coastguard Worker     // 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)
3564*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *context;
3565*61046927SAndroid Build Coastguard Worker     if (g.IO.Fonts && g.FontAtlasOwnedByContext)
3566*61046927SAndroid Build Coastguard Worker     {
3567*61046927SAndroid Build Coastguard Worker         g.IO.Fonts->Locked = false;
3568*61046927SAndroid Build Coastguard Worker         IM_DELETE(g.IO.Fonts);
3569*61046927SAndroid Build Coastguard Worker     }
3570*61046927SAndroid Build Coastguard Worker     g.IO.Fonts = NULL;
3571*61046927SAndroid Build Coastguard Worker 
3572*61046927SAndroid Build Coastguard Worker     // Cleanup of other data are conditional on actually having initialized ImGui.
3573*61046927SAndroid Build Coastguard Worker     if (!g.Initialized)
3574*61046927SAndroid Build Coastguard Worker         return;
3575*61046927SAndroid Build Coastguard Worker 
3576*61046927SAndroid Build Coastguard Worker     // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
3577*61046927SAndroid Build Coastguard Worker     if (g.SettingsLoaded && g.IO.IniFilename != NULL)
3578*61046927SAndroid Build Coastguard Worker     {
3579*61046927SAndroid Build Coastguard Worker         ImGuiContext* backup_context = GImGui;
3580*61046927SAndroid Build Coastguard Worker         SetCurrentContext(context);
3581*61046927SAndroid Build Coastguard Worker         SaveIniSettingsToDisk(g.IO.IniFilename);
3582*61046927SAndroid Build Coastguard Worker         SetCurrentContext(backup_context);
3583*61046927SAndroid Build Coastguard Worker     }
3584*61046927SAndroid Build Coastguard Worker 
3585*61046927SAndroid Build Coastguard Worker     // Clear everything else
3586*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < g.Windows.Size; i++)
3587*61046927SAndroid Build Coastguard Worker         IM_DELETE(g.Windows[i]);
3588*61046927SAndroid Build Coastguard Worker     g.Windows.clear();
3589*61046927SAndroid Build Coastguard Worker     g.WindowsFocusOrder.clear();
3590*61046927SAndroid Build Coastguard Worker     g.WindowsSortBuffer.clear();
3591*61046927SAndroid Build Coastguard Worker     g.CurrentWindow = NULL;
3592*61046927SAndroid Build Coastguard Worker     g.CurrentWindowStack.clear();
3593*61046927SAndroid Build Coastguard Worker     g.WindowsById.Clear();
3594*61046927SAndroid Build Coastguard Worker     g.NavWindow = NULL;
3595*61046927SAndroid Build Coastguard Worker     g.HoveredWindow = g.HoveredRootWindow = NULL;
3596*61046927SAndroid Build Coastguard Worker     g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
3597*61046927SAndroid Build Coastguard Worker     g.MovingWindow = NULL;
3598*61046927SAndroid Build Coastguard Worker     g.ColorModifiers.clear();
3599*61046927SAndroid Build Coastguard Worker     g.StyleModifiers.clear();
3600*61046927SAndroid Build Coastguard Worker     g.FontStack.clear();
3601*61046927SAndroid Build Coastguard Worker     g.OpenPopupStack.clear();
3602*61046927SAndroid Build Coastguard Worker     g.BeginPopupStack.clear();
3603*61046927SAndroid Build Coastguard Worker     g.DrawDataBuilder.ClearFreeMemory();
3604*61046927SAndroid Build Coastguard Worker     g.OverlayDrawList.ClearFreeMemory();
3605*61046927SAndroid Build Coastguard Worker     g.PrivateClipboard.clear();
3606*61046927SAndroid Build Coastguard Worker     g.InputTextState.TextW.clear();
3607*61046927SAndroid Build Coastguard Worker     g.InputTextState.InitialText.clear();
3608*61046927SAndroid Build Coastguard Worker     g.InputTextState.TempBuffer.clear();
3609*61046927SAndroid Build Coastguard Worker 
3610*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < g.SettingsWindows.Size; i++)
3611*61046927SAndroid Build Coastguard Worker         IM_DELETE(g.SettingsWindows[i].Name);
3612*61046927SAndroid Build Coastguard Worker     g.SettingsWindows.clear();
3613*61046927SAndroid Build Coastguard Worker     g.SettingsHandlers.clear();
3614*61046927SAndroid Build Coastguard Worker 
3615*61046927SAndroid Build Coastguard Worker     if (g.LogFile && g.LogFile != stdout)
3616*61046927SAndroid Build Coastguard Worker     {
3617*61046927SAndroid Build Coastguard Worker         fclose(g.LogFile);
3618*61046927SAndroid Build Coastguard Worker         g.LogFile = NULL;
3619*61046927SAndroid Build Coastguard Worker     }
3620*61046927SAndroid Build Coastguard Worker     g.LogClipboard.clear();
3621*61046927SAndroid Build Coastguard Worker 
3622*61046927SAndroid Build Coastguard Worker     g.Initialized = false;
3623*61046927SAndroid Build Coastguard Worker }
3624*61046927SAndroid Build Coastguard Worker 
3625*61046927SAndroid Build Coastguard Worker // FIXME: Add a more explicit sort order in the window structure.
ChildWindowComparer(const void * lhs,const void * rhs)3626*61046927SAndroid Build Coastguard Worker static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
3627*61046927SAndroid Build Coastguard Worker {
3628*61046927SAndroid Build Coastguard Worker     const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs;
3629*61046927SAndroid Build Coastguard Worker     const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs;
3630*61046927SAndroid Build Coastguard Worker     if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
3631*61046927SAndroid Build Coastguard Worker         return d;
3632*61046927SAndroid Build Coastguard Worker     if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
3633*61046927SAndroid Build Coastguard Worker         return d;
3634*61046927SAndroid Build Coastguard Worker     return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
3635*61046927SAndroid Build Coastguard Worker }
3636*61046927SAndroid Build Coastguard Worker 
AddWindowToSortBuffer(ImVector<ImGuiWindow * > * out_sorted_windows,ImGuiWindow * window)3637*61046927SAndroid Build Coastguard Worker static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
3638*61046927SAndroid Build Coastguard Worker {
3639*61046927SAndroid Build Coastguard Worker     out_sorted_windows->push_back(window);
3640*61046927SAndroid Build Coastguard Worker     if (window->Active)
3641*61046927SAndroid Build Coastguard Worker     {
3642*61046927SAndroid Build Coastguard Worker         int count = window->DC.ChildWindows.Size;
3643*61046927SAndroid Build Coastguard Worker         if (count > 1)
3644*61046927SAndroid Build Coastguard Worker             ImQsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
3645*61046927SAndroid Build Coastguard Worker         for (int i = 0; i < count; i++)
3646*61046927SAndroid Build Coastguard Worker         {
3647*61046927SAndroid Build Coastguard Worker             ImGuiWindow* child = window->DC.ChildWindows[i];
3648*61046927SAndroid Build Coastguard Worker             if (child->Active)
3649*61046927SAndroid Build Coastguard Worker                 AddWindowToSortBuffer(out_sorted_windows, child);
3650*61046927SAndroid Build Coastguard Worker         }
3651*61046927SAndroid Build Coastguard Worker     }
3652*61046927SAndroid Build Coastguard Worker }
3653*61046927SAndroid Build Coastguard Worker 
AddDrawListToDrawData(ImVector<ImDrawList * > * out_list,ImDrawList * draw_list)3654*61046927SAndroid Build Coastguard Worker static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
3655*61046927SAndroid Build Coastguard Worker {
3656*61046927SAndroid Build Coastguard Worker     if (draw_list->CmdBuffer.empty())
3657*61046927SAndroid Build Coastguard Worker         return;
3658*61046927SAndroid Build Coastguard Worker 
3659*61046927SAndroid Build Coastguard Worker     // Remove trailing command if unused
3660*61046927SAndroid Build Coastguard Worker     ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();
3661*61046927SAndroid Build Coastguard Worker     if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)
3662*61046927SAndroid Build Coastguard Worker     {
3663*61046927SAndroid Build Coastguard Worker         draw_list->CmdBuffer.pop_back();
3664*61046927SAndroid Build Coastguard Worker         if (draw_list->CmdBuffer.empty())
3665*61046927SAndroid Build Coastguard Worker             return;
3666*61046927SAndroid Build Coastguard Worker     }
3667*61046927SAndroid Build Coastguard Worker 
3668*61046927SAndroid Build Coastguard Worker     // 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.
3669*61046927SAndroid Build Coastguard Worker     IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
3670*61046927SAndroid Build Coastguard Worker     IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
3671*61046927SAndroid Build Coastguard Worker     IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
3672*61046927SAndroid Build Coastguard Worker 
3673*61046927SAndroid Build Coastguard Worker     // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
3674*61046927SAndroid Build Coastguard Worker     // If this assert triggers because you are drawing lots of stuff manually:
3675*61046927SAndroid Build Coastguard Worker     // 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.
3676*61046927SAndroid Build Coastguard Worker     // 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.
3677*61046927SAndroid Build Coastguard Worker     //    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:
3678*61046927SAndroid Build Coastguard Worker     //      glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
3679*61046927SAndroid Build Coastguard Worker     //    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.
3680*61046927SAndroid Build Coastguard Worker     // 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.
3681*61046927SAndroid Build Coastguard Worker     if (sizeof(ImDrawIdx) == 2)
3682*61046927SAndroid Build Coastguard Worker         IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
3683*61046927SAndroid Build Coastguard Worker 
3684*61046927SAndroid Build Coastguard Worker     out_list->push_back(draw_list);
3685*61046927SAndroid Build Coastguard Worker }
3686*61046927SAndroid Build Coastguard Worker 
AddWindowToDrawData(ImVector<ImDrawList * > * out_render_list,ImGuiWindow * window)3687*61046927SAndroid Build Coastguard Worker static void AddWindowToDrawData(ImVector<ImDrawList*>* out_render_list, ImGuiWindow* window)
3688*61046927SAndroid Build Coastguard Worker {
3689*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3690*61046927SAndroid Build Coastguard Worker     g.IO.MetricsRenderWindows++;
3691*61046927SAndroid Build Coastguard Worker     AddDrawListToDrawData(out_render_list, window->DrawList);
3692*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < window->DC.ChildWindows.Size; i++)
3693*61046927SAndroid Build Coastguard Worker     {
3694*61046927SAndroid Build Coastguard Worker         ImGuiWindow* child = window->DC.ChildWindows[i];
3695*61046927SAndroid Build Coastguard Worker         if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active
3696*61046927SAndroid Build Coastguard Worker             AddWindowToDrawData(out_render_list, child);
3697*61046927SAndroid Build Coastguard Worker     }
3698*61046927SAndroid Build Coastguard Worker }
3699*61046927SAndroid Build Coastguard Worker 
AddRootWindowToDrawData(ImGuiWindow * window)3700*61046927SAndroid Build Coastguard Worker static void AddRootWindowToDrawData(ImGuiWindow* window)
3701*61046927SAndroid Build Coastguard Worker {
3702*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3703*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Tooltip)
3704*61046927SAndroid Build Coastguard Worker         AddWindowToDrawData(&g.DrawDataBuilder.Layers[1], window);
3705*61046927SAndroid Build Coastguard Worker     else
3706*61046927SAndroid Build Coastguard Worker         AddWindowToDrawData(&g.DrawDataBuilder.Layers[0], window);
3707*61046927SAndroid Build Coastguard Worker }
3708*61046927SAndroid Build Coastguard Worker 
FlattenIntoSingleLayer()3709*61046927SAndroid Build Coastguard Worker void ImDrawDataBuilder::FlattenIntoSingleLayer()
3710*61046927SAndroid Build Coastguard Worker {
3711*61046927SAndroid Build Coastguard Worker     int n = Layers[0].Size;
3712*61046927SAndroid Build Coastguard Worker     int size = n;
3713*61046927SAndroid Build Coastguard Worker     for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
3714*61046927SAndroid Build Coastguard Worker         size += Layers[i].Size;
3715*61046927SAndroid Build Coastguard Worker     Layers[0].resize(size);
3716*61046927SAndroid Build Coastguard Worker     for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
3717*61046927SAndroid Build Coastguard Worker     {
3718*61046927SAndroid Build Coastguard Worker         ImVector<ImDrawList*>& layer = Layers[layer_n];
3719*61046927SAndroid Build Coastguard Worker         if (layer.empty())
3720*61046927SAndroid Build Coastguard Worker             continue;
3721*61046927SAndroid Build Coastguard Worker         memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
3722*61046927SAndroid Build Coastguard Worker         n += layer.Size;
3723*61046927SAndroid Build Coastguard Worker         layer.resize(0);
3724*61046927SAndroid Build Coastguard Worker     }
3725*61046927SAndroid Build Coastguard Worker }
3726*61046927SAndroid Build Coastguard Worker 
SetupDrawData(ImVector<ImDrawList * > * draw_lists,ImDrawData * draw_data)3727*61046927SAndroid Build Coastguard Worker static void SetupDrawData(ImVector<ImDrawList*>* draw_lists, ImDrawData* draw_data)
3728*61046927SAndroid Build Coastguard Worker {
3729*61046927SAndroid Build Coastguard Worker     ImGuiIO& io = ImGui::GetIO();
3730*61046927SAndroid Build Coastguard Worker     draw_data->Valid = true;
3731*61046927SAndroid Build Coastguard Worker     draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL;
3732*61046927SAndroid Build Coastguard Worker     draw_data->CmdListsCount = draw_lists->Size;
3733*61046927SAndroid Build Coastguard Worker     draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
3734*61046927SAndroid Build Coastguard Worker     draw_data->DisplayPos = ImVec2(0.0f, 0.0f);
3735*61046927SAndroid Build Coastguard Worker     draw_data->DisplaySize = io.DisplaySize;
3736*61046927SAndroid Build Coastguard Worker     draw_data->FramebufferScale = io.DisplayFramebufferScale;
3737*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < draw_lists->Size; n++)
3738*61046927SAndroid Build Coastguard Worker     {
3739*61046927SAndroid Build Coastguard Worker         draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size;
3740*61046927SAndroid Build Coastguard Worker         draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size;
3741*61046927SAndroid Build Coastguard Worker     }
3742*61046927SAndroid Build Coastguard Worker }
3743*61046927SAndroid Build Coastguard Worker 
3744*61046927SAndroid Build Coastguard Worker // 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.
PushClipRect(const ImVec2 & clip_rect_min,const ImVec2 & clip_rect_max,bool intersect_with_current_clip_rect)3745*61046927SAndroid Build Coastguard Worker void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
3746*61046927SAndroid Build Coastguard Worker {
3747*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
3748*61046927SAndroid Build Coastguard Worker     window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
3749*61046927SAndroid Build Coastguard Worker     window->ClipRect = window->DrawList->_ClipRectStack.back();
3750*61046927SAndroid Build Coastguard Worker }
3751*61046927SAndroid Build Coastguard Worker 
PopClipRect()3752*61046927SAndroid Build Coastguard Worker void ImGui::PopClipRect()
3753*61046927SAndroid Build Coastguard Worker {
3754*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
3755*61046927SAndroid Build Coastguard Worker     window->DrawList->PopClipRect();
3756*61046927SAndroid Build Coastguard Worker     window->ClipRect = window->DrawList->_ClipRectStack.back();
3757*61046927SAndroid Build Coastguard Worker }
3758*61046927SAndroid Build Coastguard Worker 
3759*61046927SAndroid Build Coastguard Worker // 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.
EndFrame()3760*61046927SAndroid Build Coastguard Worker void ImGui::EndFrame()
3761*61046927SAndroid Build Coastguard Worker {
3762*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3763*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Initialized);
3764*61046927SAndroid Build Coastguard Worker     if (g.FrameCountEnded == g.FrameCount)          // Don't process EndFrame() multiple times.
3765*61046927SAndroid Build Coastguard Worker         return;
3766*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?");
3767*61046927SAndroid Build Coastguard Worker 
3768*61046927SAndroid Build Coastguard Worker     // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
3769*61046927SAndroid Build Coastguard Worker     if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f))
3770*61046927SAndroid Build Coastguard Worker     {
3771*61046927SAndroid Build Coastguard Worker         g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y);
3772*61046927SAndroid Build Coastguard Worker         g.PlatformImeLastPos = g.PlatformImePos;
3773*61046927SAndroid Build Coastguard Worker     }
3774*61046927SAndroid Build Coastguard Worker 
3775*61046927SAndroid Build Coastguard Worker     // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
3776*61046927SAndroid Build Coastguard Worker     // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
3777*61046927SAndroid Build Coastguard Worker     if (g.CurrentWindowStack.Size != 1)
3778*61046927SAndroid Build Coastguard Worker     {
3779*61046927SAndroid Build Coastguard Worker         if (g.CurrentWindowStack.Size > 1)
3780*61046927SAndroid Build Coastguard Worker         {
3781*61046927SAndroid Build Coastguard Worker             IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
3782*61046927SAndroid Build Coastguard Worker             while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING
3783*61046927SAndroid Build Coastguard Worker                 End();
3784*61046927SAndroid Build Coastguard Worker         }
3785*61046927SAndroid Build Coastguard Worker         else
3786*61046927SAndroid Build Coastguard Worker         {
3787*61046927SAndroid Build Coastguard Worker             IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
3788*61046927SAndroid Build Coastguard Worker         }
3789*61046927SAndroid Build Coastguard Worker     }
3790*61046927SAndroid Build Coastguard Worker 
3791*61046927SAndroid Build Coastguard Worker     // Hide implicit/fallback "Debug" window if it hasn't been used
3792*61046927SAndroid Build Coastguard Worker     g.FrameScopePushedImplicitWindow = false;
3793*61046927SAndroid Build Coastguard Worker     if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
3794*61046927SAndroid Build Coastguard Worker         g.CurrentWindow->Active = false;
3795*61046927SAndroid Build Coastguard Worker     End();
3796*61046927SAndroid Build Coastguard Worker 
3797*61046927SAndroid Build Coastguard Worker     // Show CTRL+TAB list window
3798*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget)
3799*61046927SAndroid Build Coastguard Worker         NavUpdateWindowingList();
3800*61046927SAndroid Build Coastguard Worker 
3801*61046927SAndroid Build Coastguard Worker     // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
3802*61046927SAndroid Build Coastguard Worker     if (g.DragDropActive)
3803*61046927SAndroid Build Coastguard Worker     {
3804*61046927SAndroid Build Coastguard Worker         bool is_delivered = g.DragDropPayload.Delivery;
3805*61046927SAndroid Build Coastguard Worker         bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton));
3806*61046927SAndroid Build Coastguard Worker         if (is_delivered || is_elapsed)
3807*61046927SAndroid Build Coastguard Worker             ClearDragDrop();
3808*61046927SAndroid Build Coastguard Worker     }
3809*61046927SAndroid Build Coastguard Worker 
3810*61046927SAndroid Build Coastguard Worker     // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing.
3811*61046927SAndroid Build Coastguard Worker     if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount)
3812*61046927SAndroid Build Coastguard Worker     {
3813*61046927SAndroid Build Coastguard Worker         g.DragDropWithinSourceOrTarget = true;
3814*61046927SAndroid Build Coastguard Worker         SetTooltip("...");
3815*61046927SAndroid Build Coastguard Worker         g.DragDropWithinSourceOrTarget = false;
3816*61046927SAndroid Build Coastguard Worker     }
3817*61046927SAndroid Build Coastguard Worker 
3818*61046927SAndroid Build Coastguard Worker     // End frame
3819*61046927SAndroid Build Coastguard Worker     g.FrameScopeActive = false;
3820*61046927SAndroid Build Coastguard Worker     g.FrameCountEnded = g.FrameCount;
3821*61046927SAndroid Build Coastguard Worker 
3822*61046927SAndroid Build Coastguard Worker     // Initiate moving window + handle left-click and right-click focus
3823*61046927SAndroid Build Coastguard Worker     UpdateMouseMovingWindowEndFrame();
3824*61046927SAndroid Build Coastguard Worker 
3825*61046927SAndroid Build Coastguard Worker     // Sort the window list so that all child windows are after their parent
3826*61046927SAndroid Build Coastguard Worker     // We cannot do that on FocusWindow() because childs may not exist yet
3827*61046927SAndroid Build Coastguard Worker     g.WindowsSortBuffer.resize(0);
3828*61046927SAndroid Build Coastguard Worker     g.WindowsSortBuffer.reserve(g.Windows.Size);
3829*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != g.Windows.Size; i++)
3830*61046927SAndroid Build Coastguard Worker     {
3831*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.Windows[i];
3832*61046927SAndroid Build Coastguard Worker         if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))       // if a child is active its parent will add it
3833*61046927SAndroid Build Coastguard Worker             continue;
3834*61046927SAndroid Build Coastguard Worker         AddWindowToSortBuffer(&g.WindowsSortBuffer, window);
3835*61046927SAndroid Build Coastguard Worker     }
3836*61046927SAndroid Build Coastguard Worker 
3837*61046927SAndroid Build Coastguard Worker     // This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong.
3838*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);
3839*61046927SAndroid Build Coastguard Worker     g.Windows.swap(g.WindowsSortBuffer);
3840*61046927SAndroid Build Coastguard Worker     g.IO.MetricsActiveWindows = g.WindowsActiveCount;
3841*61046927SAndroid Build Coastguard Worker 
3842*61046927SAndroid Build Coastguard Worker     // Unlock font atlas
3843*61046927SAndroid Build Coastguard Worker     g.IO.Fonts->Locked = false;
3844*61046927SAndroid Build Coastguard Worker 
3845*61046927SAndroid Build Coastguard Worker     // Clear Input data for next frame
3846*61046927SAndroid Build Coastguard Worker     g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
3847*61046927SAndroid Build Coastguard Worker     g.IO.InputQueueCharacters.resize(0);
3848*61046927SAndroid Build Coastguard Worker     memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs));
3849*61046927SAndroid Build Coastguard Worker }
3850*61046927SAndroid Build Coastguard Worker 
Render()3851*61046927SAndroid Build Coastguard Worker void ImGui::Render()
3852*61046927SAndroid Build Coastguard Worker {
3853*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3854*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Initialized);
3855*61046927SAndroid Build Coastguard Worker 
3856*61046927SAndroid Build Coastguard Worker     if (g.FrameCountEnded != g.FrameCount)
3857*61046927SAndroid Build Coastguard Worker         EndFrame();
3858*61046927SAndroid Build Coastguard Worker     g.FrameCountRendered = g.FrameCount;
3859*61046927SAndroid Build Coastguard Worker 
3860*61046927SAndroid Build Coastguard Worker     // Gather ImDrawList to render (for each active window)
3861*61046927SAndroid Build Coastguard Worker     g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsRenderWindows = 0;
3862*61046927SAndroid Build Coastguard Worker     g.DrawDataBuilder.Clear();
3863*61046927SAndroid Build Coastguard Worker     ImGuiWindow* windows_to_render_front_most[2];
3864*61046927SAndroid Build Coastguard Worker     windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
3865*61046927SAndroid Build Coastguard Worker     windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL;
3866*61046927SAndroid Build Coastguard Worker     for (int n = 0; n != g.Windows.Size; n++)
3867*61046927SAndroid Build Coastguard Worker     {
3868*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.Windows[n];
3869*61046927SAndroid Build Coastguard Worker         if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1])
3870*61046927SAndroid Build Coastguard Worker             AddRootWindowToDrawData(window);
3871*61046927SAndroid Build Coastguard Worker     }
3872*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++)
3873*61046927SAndroid Build Coastguard Worker         if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window
3874*61046927SAndroid Build Coastguard Worker             AddRootWindowToDrawData(windows_to_render_front_most[n]);
3875*61046927SAndroid Build Coastguard Worker     g.DrawDataBuilder.FlattenIntoSingleLayer();
3876*61046927SAndroid Build Coastguard Worker 
3877*61046927SAndroid Build Coastguard Worker     // Draw software mouse cursor if requested
3878*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseDrawCursor)
3879*61046927SAndroid Build Coastguard Worker         RenderMouseCursor(&g.OverlayDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor);
3880*61046927SAndroid Build Coastguard Worker 
3881*61046927SAndroid Build Coastguard Worker     if (!g.OverlayDrawList.VtxBuffer.empty())
3882*61046927SAndroid Build Coastguard Worker         AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList);
3883*61046927SAndroid Build Coastguard Worker 
3884*61046927SAndroid Build Coastguard Worker     // Setup ImDrawData structure for end-user
3885*61046927SAndroid Build Coastguard Worker     SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData);
3886*61046927SAndroid Build Coastguard Worker     g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount;
3887*61046927SAndroid Build Coastguard Worker     g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount;
3888*61046927SAndroid Build Coastguard Worker 
3889*61046927SAndroid Build Coastguard Worker     // (Legacy) Call the Render callback function. The current prefer way is to let the user retrieve GetDrawData() and call the render function themselves.
3890*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3891*61046927SAndroid Build Coastguard Worker     if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
3892*61046927SAndroid Build Coastguard Worker         g.IO.RenderDrawListsFn(&g.DrawData);
3893*61046927SAndroid Build Coastguard Worker #endif
3894*61046927SAndroid Build Coastguard Worker }
3895*61046927SAndroid Build Coastguard Worker 
3896*61046927SAndroid Build Coastguard Worker // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
3897*61046927SAndroid Build Coastguard Worker // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize)
CalcTextSize(const char * text,const char * text_end,bool hide_text_after_double_hash,float wrap_width)3898*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
3899*61046927SAndroid Build Coastguard Worker {
3900*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3901*61046927SAndroid Build Coastguard Worker 
3902*61046927SAndroid Build Coastguard Worker     const char* text_display_end;
3903*61046927SAndroid Build Coastguard Worker     if (hide_text_after_double_hash)
3904*61046927SAndroid Build Coastguard Worker         text_display_end = FindRenderedTextEnd(text, text_end);      // Hide anything after a '##' string
3905*61046927SAndroid Build Coastguard Worker     else
3906*61046927SAndroid Build Coastguard Worker         text_display_end = text_end;
3907*61046927SAndroid Build Coastguard Worker 
3908*61046927SAndroid Build Coastguard Worker     ImFont* font = g.Font;
3909*61046927SAndroid Build Coastguard Worker     const float font_size = g.FontSize;
3910*61046927SAndroid Build Coastguard Worker     if (text == text_display_end)
3911*61046927SAndroid Build Coastguard Worker         return ImVec2(0.0f, font_size);
3912*61046927SAndroid Build Coastguard Worker     ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
3913*61046927SAndroid Build Coastguard Worker 
3914*61046927SAndroid Build Coastguard Worker     // Round
3915*61046927SAndroid Build Coastguard Worker     text_size.x = (float)(int)(text_size.x + 0.95f);
3916*61046927SAndroid Build Coastguard Worker 
3917*61046927SAndroid Build Coastguard Worker     return text_size;
3918*61046927SAndroid Build Coastguard Worker }
3919*61046927SAndroid Build Coastguard Worker 
3920*61046927SAndroid Build Coastguard Worker // Helper to calculate coarse clipping of large list of evenly sized items.
3921*61046927SAndroid Build Coastguard Worker // NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
3922*61046927SAndroid Build Coastguard Worker // NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
CalcListClipping(int items_count,float items_height,int * out_items_display_start,int * out_items_display_end)3923*61046927SAndroid Build Coastguard Worker void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
3924*61046927SAndroid Build Coastguard Worker {
3925*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3926*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
3927*61046927SAndroid Build Coastguard Worker     if (g.LogEnabled)
3928*61046927SAndroid Build Coastguard Worker     {
3929*61046927SAndroid Build Coastguard Worker         // If logging is active, do not perform any clipping
3930*61046927SAndroid Build Coastguard Worker         *out_items_display_start = 0;
3931*61046927SAndroid Build Coastguard Worker         *out_items_display_end = items_count;
3932*61046927SAndroid Build Coastguard Worker         return;
3933*61046927SAndroid Build Coastguard Worker     }
3934*61046927SAndroid Build Coastguard Worker     if (window->SkipItems)
3935*61046927SAndroid Build Coastguard Worker     {
3936*61046927SAndroid Build Coastguard Worker         *out_items_display_start = *out_items_display_end = 0;
3937*61046927SAndroid Build Coastguard Worker         return;
3938*61046927SAndroid Build Coastguard Worker     }
3939*61046927SAndroid Build Coastguard Worker 
3940*61046927SAndroid Build Coastguard Worker     // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect
3941*61046927SAndroid Build Coastguard Worker     ImRect unclipped_rect = window->ClipRect;
3942*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest)
3943*61046927SAndroid Build Coastguard Worker         unclipped_rect.Add(g.NavScoringRectScreen);
3944*61046927SAndroid Build Coastguard Worker 
3945*61046927SAndroid Build Coastguard Worker     const ImVec2 pos = window->DC.CursorPos;
3946*61046927SAndroid Build Coastguard Worker     int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
3947*61046927SAndroid Build Coastguard Worker     int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
3948*61046927SAndroid Build Coastguard Worker 
3949*61046927SAndroid Build Coastguard Worker     // When performing a navigation request, ensure we have one item extra in the direction we are moving to
3950*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up)
3951*61046927SAndroid Build Coastguard Worker         start--;
3952*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down)
3953*61046927SAndroid Build Coastguard Worker         end++;
3954*61046927SAndroid Build Coastguard Worker 
3955*61046927SAndroid Build Coastguard Worker     start = ImClamp(start, 0, items_count);
3956*61046927SAndroid Build Coastguard Worker     end = ImClamp(end + 1, start, items_count);
3957*61046927SAndroid Build Coastguard Worker     *out_items_display_start = start;
3958*61046927SAndroid Build Coastguard Worker     *out_items_display_end = end;
3959*61046927SAndroid Build Coastguard Worker }
3960*61046927SAndroid Build Coastguard Worker 
3961*61046927SAndroid Build Coastguard Worker // Find window given position, search front-to-back
3962*61046927SAndroid Build Coastguard Worker // FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programatically
3963*61046927SAndroid Build Coastguard Worker // with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is
3964*61046927SAndroid Build Coastguard Worker // called, aka before the next Begin(). Moving window isn't affected.
FindHoveredWindow()3965*61046927SAndroid Build Coastguard Worker static void FindHoveredWindow()
3966*61046927SAndroid Build Coastguard Worker {
3967*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
3968*61046927SAndroid Build Coastguard Worker 
3969*61046927SAndroid Build Coastguard Worker     ImGuiWindow* hovered_window = NULL;
3970*61046927SAndroid Build Coastguard Worker     if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
3971*61046927SAndroid Build Coastguard Worker         hovered_window = g.MovingWindow;
3972*61046927SAndroid Build Coastguard Worker 
3973*61046927SAndroid Build Coastguard Worker     ImVec2 padding_regular = g.Style.TouchExtraPadding;
3974*61046927SAndroid Build Coastguard Worker     ImVec2 padding_for_resize_from_edges = g.IO.ConfigWindowsResizeFromEdges ? ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS)) : padding_regular;
3975*61046927SAndroid Build Coastguard Worker     for (int i = g.Windows.Size - 1; i >= 0; i--)
3976*61046927SAndroid Build Coastguard Worker     {
3977*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.Windows[i];
3978*61046927SAndroid Build Coastguard Worker         if (!window->Active || window->Hidden)
3979*61046927SAndroid Build Coastguard Worker             continue;
3980*61046927SAndroid Build Coastguard Worker         if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
3981*61046927SAndroid Build Coastguard Worker             continue;
3982*61046927SAndroid Build Coastguard Worker 
3983*61046927SAndroid Build Coastguard Worker         // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
3984*61046927SAndroid Build Coastguard Worker         ImRect bb(window->OuterRectClipped);
3985*61046927SAndroid Build Coastguard Worker         if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize))
3986*61046927SAndroid Build Coastguard Worker             bb.Expand(padding_regular);
3987*61046927SAndroid Build Coastguard Worker         else
3988*61046927SAndroid Build Coastguard Worker             bb.Expand(padding_for_resize_from_edges);
3989*61046927SAndroid Build Coastguard Worker         if (!bb.Contains(g.IO.MousePos))
3990*61046927SAndroid Build Coastguard Worker             continue;
3991*61046927SAndroid Build Coastguard Worker 
3992*61046927SAndroid Build Coastguard Worker         // Those seemingly unnecessary extra tests are because the code here is a little different in viewport/docking branches.
3993*61046927SAndroid Build Coastguard Worker         if (hovered_window == NULL)
3994*61046927SAndroid Build Coastguard Worker             hovered_window = window;
3995*61046927SAndroid Build Coastguard Worker         if (hovered_window)
3996*61046927SAndroid Build Coastguard Worker             break;
3997*61046927SAndroid Build Coastguard Worker     }
3998*61046927SAndroid Build Coastguard Worker 
3999*61046927SAndroid Build Coastguard Worker     g.HoveredWindow = hovered_window;
4000*61046927SAndroid Build Coastguard Worker     g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
4001*61046927SAndroid Build Coastguard Worker 
4002*61046927SAndroid Build Coastguard Worker }
4003*61046927SAndroid Build Coastguard Worker 
4004*61046927SAndroid Build Coastguard Worker // Test if mouse cursor is hovering given rectangle
4005*61046927SAndroid Build Coastguard Worker // NB- Rectangle is clipped by our current clip setting
4006*61046927SAndroid Build Coastguard Worker // NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
IsMouseHoveringRect(const ImVec2 & r_min,const ImVec2 & r_max,bool clip)4007*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
4008*61046927SAndroid Build Coastguard Worker {
4009*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4010*61046927SAndroid Build Coastguard Worker 
4011*61046927SAndroid Build Coastguard Worker     // Clip
4012*61046927SAndroid Build Coastguard Worker     ImRect rect_clipped(r_min, r_max);
4013*61046927SAndroid Build Coastguard Worker     if (clip)
4014*61046927SAndroid Build Coastguard Worker         rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
4015*61046927SAndroid Build Coastguard Worker 
4016*61046927SAndroid Build Coastguard Worker     // Expand for touch input
4017*61046927SAndroid Build Coastguard Worker     const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
4018*61046927SAndroid Build Coastguard Worker     if (!rect_for_touch.Contains(g.IO.MousePos))
4019*61046927SAndroid Build Coastguard Worker         return false;
4020*61046927SAndroid Build Coastguard Worker     return true;
4021*61046927SAndroid Build Coastguard Worker }
4022*61046927SAndroid Build Coastguard Worker 
GetKeyIndex(ImGuiKey imgui_key)4023*61046927SAndroid Build Coastguard Worker int ImGui::GetKeyIndex(ImGuiKey imgui_key)
4024*61046927SAndroid Build Coastguard Worker {
4025*61046927SAndroid Build Coastguard Worker     IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
4026*61046927SAndroid Build Coastguard Worker     return GImGui->IO.KeyMap[imgui_key];
4027*61046927SAndroid Build Coastguard Worker }
4028*61046927SAndroid Build Coastguard Worker 
4029*61046927SAndroid Build Coastguard Worker // 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[]!
IsKeyDown(int user_key_index)4030*61046927SAndroid Build Coastguard Worker bool ImGui::IsKeyDown(int user_key_index)
4031*61046927SAndroid Build Coastguard Worker {
4032*61046927SAndroid Build Coastguard Worker     if (user_key_index < 0) return false;
4033*61046927SAndroid Build Coastguard Worker     IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown));
4034*61046927SAndroid Build Coastguard Worker     return GImGui->IO.KeysDown[user_key_index];
4035*61046927SAndroid Build Coastguard Worker }
4036*61046927SAndroid Build Coastguard Worker 
CalcTypematicPressedRepeatAmount(float t,float t_prev,float repeat_delay,float repeat_rate)4037*61046927SAndroid Build Coastguard Worker int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)
4038*61046927SAndroid Build Coastguard Worker {
4039*61046927SAndroid Build Coastguard Worker     if (t == 0.0f)
4040*61046927SAndroid Build Coastguard Worker         return 1;
4041*61046927SAndroid Build Coastguard Worker     if (t <= repeat_delay || repeat_rate <= 0.0f)
4042*61046927SAndroid Build Coastguard Worker         return 0;
4043*61046927SAndroid Build Coastguard Worker     const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate);
4044*61046927SAndroid Build Coastguard Worker     return (count > 0) ? count : 0;
4045*61046927SAndroid Build Coastguard Worker }
4046*61046927SAndroid Build Coastguard Worker 
GetKeyPressedAmount(int key_index,float repeat_delay,float repeat_rate)4047*61046927SAndroid Build Coastguard Worker int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
4048*61046927SAndroid Build Coastguard Worker {
4049*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4050*61046927SAndroid Build Coastguard Worker     if (key_index < 0)
4051*61046927SAndroid Build Coastguard Worker         return 0;
4052*61046927SAndroid Build Coastguard Worker     IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
4053*61046927SAndroid Build Coastguard Worker     const float t = g.IO.KeysDownDuration[key_index];
4054*61046927SAndroid Build Coastguard Worker     return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate);
4055*61046927SAndroid Build Coastguard Worker }
4056*61046927SAndroid Build Coastguard Worker 
IsKeyPressed(int user_key_index,bool repeat)4057*61046927SAndroid Build Coastguard Worker bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
4058*61046927SAndroid Build Coastguard Worker {
4059*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4060*61046927SAndroid Build Coastguard Worker     if (user_key_index < 0)
4061*61046927SAndroid Build Coastguard Worker         return false;
4062*61046927SAndroid Build Coastguard Worker     IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
4063*61046927SAndroid Build Coastguard Worker     const float t = g.IO.KeysDownDuration[user_key_index];
4064*61046927SAndroid Build Coastguard Worker     if (t == 0.0f)
4065*61046927SAndroid Build Coastguard Worker         return true;
4066*61046927SAndroid Build Coastguard Worker     if (repeat && t > g.IO.KeyRepeatDelay)
4067*61046927SAndroid Build Coastguard Worker         return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
4068*61046927SAndroid Build Coastguard Worker     return false;
4069*61046927SAndroid Build Coastguard Worker }
4070*61046927SAndroid Build Coastguard Worker 
IsKeyReleased(int user_key_index)4071*61046927SAndroid Build Coastguard Worker bool ImGui::IsKeyReleased(int user_key_index)
4072*61046927SAndroid Build Coastguard Worker {
4073*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4074*61046927SAndroid Build Coastguard Worker     if (user_key_index < 0) return false;
4075*61046927SAndroid Build Coastguard Worker     IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
4076*61046927SAndroid Build Coastguard Worker     return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
4077*61046927SAndroid Build Coastguard Worker }
4078*61046927SAndroid Build Coastguard Worker 
IsMouseDown(int button)4079*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseDown(int button)
4080*61046927SAndroid Build Coastguard Worker {
4081*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4082*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4083*61046927SAndroid Build Coastguard Worker     return g.IO.MouseDown[button];
4084*61046927SAndroid Build Coastguard Worker }
4085*61046927SAndroid Build Coastguard Worker 
IsAnyMouseDown()4086*61046927SAndroid Build Coastguard Worker bool ImGui::IsAnyMouseDown()
4087*61046927SAndroid Build Coastguard Worker {
4088*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4089*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
4090*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseDown[n])
4091*61046927SAndroid Build Coastguard Worker             return true;
4092*61046927SAndroid Build Coastguard Worker     return false;
4093*61046927SAndroid Build Coastguard Worker }
4094*61046927SAndroid Build Coastguard Worker 
IsMouseClicked(int button,bool repeat)4095*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseClicked(int button, bool repeat)
4096*61046927SAndroid Build Coastguard Worker {
4097*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4098*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4099*61046927SAndroid Build Coastguard Worker     const float t = g.IO.MouseDownDuration[button];
4100*61046927SAndroid Build Coastguard Worker     if (t == 0.0f)
4101*61046927SAndroid Build Coastguard Worker         return true;
4102*61046927SAndroid Build Coastguard Worker 
4103*61046927SAndroid Build Coastguard Worker     if (repeat && t > g.IO.KeyRepeatDelay)
4104*61046927SAndroid Build Coastguard Worker     {
4105*61046927SAndroid Build Coastguard Worker         float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;
4106*61046927SAndroid Build Coastguard Worker         if ((ImFmod(t - delay, rate) > rate*0.5f) != (ImFmod(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))
4107*61046927SAndroid Build Coastguard Worker             return true;
4108*61046927SAndroid Build Coastguard Worker     }
4109*61046927SAndroid Build Coastguard Worker 
4110*61046927SAndroid Build Coastguard Worker     return false;
4111*61046927SAndroid Build Coastguard Worker }
4112*61046927SAndroid Build Coastguard Worker 
IsMouseReleased(int button)4113*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseReleased(int button)
4114*61046927SAndroid Build Coastguard Worker {
4115*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4116*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4117*61046927SAndroid Build Coastguard Worker     return g.IO.MouseReleased[button];
4118*61046927SAndroid Build Coastguard Worker }
4119*61046927SAndroid Build Coastguard Worker 
IsMouseDoubleClicked(int button)4120*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseDoubleClicked(int button)
4121*61046927SAndroid Build Coastguard Worker {
4122*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4123*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4124*61046927SAndroid Build Coastguard Worker     return g.IO.MouseDoubleClicked[button];
4125*61046927SAndroid Build Coastguard Worker }
4126*61046927SAndroid Build Coastguard Worker 
IsMouseDragging(int button,float lock_threshold)4127*61046927SAndroid Build Coastguard Worker bool ImGui::IsMouseDragging(int button, float lock_threshold)
4128*61046927SAndroid Build Coastguard Worker {
4129*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4130*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4131*61046927SAndroid Build Coastguard Worker     if (!g.IO.MouseDown[button])
4132*61046927SAndroid Build Coastguard Worker         return false;
4133*61046927SAndroid Build Coastguard Worker     if (lock_threshold < 0.0f)
4134*61046927SAndroid Build Coastguard Worker         lock_threshold = g.IO.MouseDragThreshold;
4135*61046927SAndroid Build Coastguard Worker     return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
4136*61046927SAndroid Build Coastguard Worker }
4137*61046927SAndroid Build Coastguard Worker 
GetMousePos()4138*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetMousePos()
4139*61046927SAndroid Build Coastguard Worker {
4140*61046927SAndroid Build Coastguard Worker     return GImGui->IO.MousePos;
4141*61046927SAndroid Build Coastguard Worker }
4142*61046927SAndroid Build Coastguard Worker 
4143*61046927SAndroid Build Coastguard Worker // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
GetMousePosOnOpeningCurrentPopup()4144*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
4145*61046927SAndroid Build Coastguard Worker {
4146*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4147*61046927SAndroid Build Coastguard Worker     if (g.BeginPopupStack.Size > 0)
4148*61046927SAndroid Build Coastguard Worker         return g.OpenPopupStack[g.BeginPopupStack.Size-1].OpenMousePos;
4149*61046927SAndroid Build Coastguard Worker     return g.IO.MousePos;
4150*61046927SAndroid Build Coastguard Worker }
4151*61046927SAndroid Build Coastguard Worker 
4152*61046927SAndroid Build Coastguard Worker // We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position.
IsMousePosValid(const ImVec2 * mouse_pos)4153*61046927SAndroid Build Coastguard Worker bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
4154*61046927SAndroid Build Coastguard Worker {
4155*61046927SAndroid Build Coastguard Worker     // The assert is only to silence a false-positive in XCode Static Analysis.
4156*61046927SAndroid Build Coastguard Worker     // Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions).
4157*61046927SAndroid Build Coastguard Worker     IM_ASSERT(GImGui != NULL);
4158*61046927SAndroid Build Coastguard Worker     const float MOUSE_INVALID = -256000.0f;
4159*61046927SAndroid Build Coastguard Worker     ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos;
4160*61046927SAndroid Build Coastguard Worker     return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
4161*61046927SAndroid Build Coastguard Worker }
4162*61046927SAndroid Build Coastguard Worker 
4163*61046927SAndroid Build Coastguard Worker // Return the delta from the initial clicking position.
4164*61046927SAndroid Build Coastguard Worker // This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
4165*61046927SAndroid Build Coastguard Worker // NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window.
GetMouseDragDelta(int button,float lock_threshold)4166*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
4167*61046927SAndroid Build Coastguard Worker {
4168*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4169*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4170*61046927SAndroid Build Coastguard Worker     if (lock_threshold < 0.0f)
4171*61046927SAndroid Build Coastguard Worker         lock_threshold = g.IO.MouseDragThreshold;
4172*61046927SAndroid Build Coastguard Worker     if (g.IO.MouseDown[button])
4173*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
4174*61046927SAndroid Build Coastguard Worker             return g.IO.MousePos - g.IO.MouseClickedPos[button];     // Assume we can only get active with left-mouse button (at the moment).
4175*61046927SAndroid Build Coastguard Worker     return ImVec2(0.0f, 0.0f);
4176*61046927SAndroid Build Coastguard Worker }
4177*61046927SAndroid Build Coastguard Worker 
ResetMouseDragDelta(int button)4178*61046927SAndroid Build Coastguard Worker void ImGui::ResetMouseDragDelta(int button)
4179*61046927SAndroid Build Coastguard Worker {
4180*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4181*61046927SAndroid Build Coastguard Worker     IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
4182*61046927SAndroid Build Coastguard Worker     // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
4183*61046927SAndroid Build Coastguard Worker     g.IO.MouseClickedPos[button] = g.IO.MousePos;
4184*61046927SAndroid Build Coastguard Worker }
4185*61046927SAndroid Build Coastguard Worker 
GetMouseCursor()4186*61046927SAndroid Build Coastguard Worker ImGuiMouseCursor ImGui::GetMouseCursor()
4187*61046927SAndroid Build Coastguard Worker {
4188*61046927SAndroid Build Coastguard Worker     return GImGui->MouseCursor;
4189*61046927SAndroid Build Coastguard Worker }
4190*61046927SAndroid Build Coastguard Worker 
SetMouseCursor(ImGuiMouseCursor cursor_type)4191*61046927SAndroid Build Coastguard Worker void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
4192*61046927SAndroid Build Coastguard Worker {
4193*61046927SAndroid Build Coastguard Worker     GImGui->MouseCursor = cursor_type;
4194*61046927SAndroid Build Coastguard Worker }
4195*61046927SAndroid Build Coastguard Worker 
CaptureKeyboardFromApp(bool capture)4196*61046927SAndroid Build Coastguard Worker void ImGui::CaptureKeyboardFromApp(bool capture)
4197*61046927SAndroid Build Coastguard Worker {
4198*61046927SAndroid Build Coastguard Worker     GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;
4199*61046927SAndroid Build Coastguard Worker }
4200*61046927SAndroid Build Coastguard Worker 
CaptureMouseFromApp(bool capture)4201*61046927SAndroid Build Coastguard Worker void ImGui::CaptureMouseFromApp(bool capture)
4202*61046927SAndroid Build Coastguard Worker {
4203*61046927SAndroid Build Coastguard Worker     GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;
4204*61046927SAndroid Build Coastguard Worker }
4205*61046927SAndroid Build Coastguard Worker 
IsItemActive()4206*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemActive()
4207*61046927SAndroid Build Coastguard Worker {
4208*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4209*61046927SAndroid Build Coastguard Worker     if (g.ActiveId)
4210*61046927SAndroid Build Coastguard Worker     {
4211*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.CurrentWindow;
4212*61046927SAndroid Build Coastguard Worker         return g.ActiveId == window->DC.LastItemId;
4213*61046927SAndroid Build Coastguard Worker     }
4214*61046927SAndroid Build Coastguard Worker     return false;
4215*61046927SAndroid Build Coastguard Worker }
4216*61046927SAndroid Build Coastguard Worker 
IsItemActivated()4217*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemActivated()
4218*61046927SAndroid Build Coastguard Worker {
4219*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4220*61046927SAndroid Build Coastguard Worker     if (g.ActiveId)
4221*61046927SAndroid Build Coastguard Worker     {
4222*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.CurrentWindow;
4223*61046927SAndroid Build Coastguard Worker         if (g.ActiveId == window->DC.LastItemId && g.ActiveIdPreviousFrame != window->DC.LastItemId)
4224*61046927SAndroid Build Coastguard Worker             return true;
4225*61046927SAndroid Build Coastguard Worker     }
4226*61046927SAndroid Build Coastguard Worker     return false;
4227*61046927SAndroid Build Coastguard Worker }
4228*61046927SAndroid Build Coastguard Worker 
IsItemDeactivated()4229*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemDeactivated()
4230*61046927SAndroid Build Coastguard Worker {
4231*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4232*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
4233*61046927SAndroid Build Coastguard Worker     return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
4234*61046927SAndroid Build Coastguard Worker }
4235*61046927SAndroid Build Coastguard Worker 
IsItemDeactivatedAfterEdit()4236*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemDeactivatedAfterEdit()
4237*61046927SAndroid Build Coastguard Worker {
4238*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4239*61046927SAndroid Build Coastguard Worker     return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEdited || (g.ActiveId == 0 && g.ActiveIdHasBeenEdited));
4240*61046927SAndroid Build Coastguard Worker }
4241*61046927SAndroid Build Coastguard Worker 
IsItemFocused()4242*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemFocused()
4243*61046927SAndroid Build Coastguard Worker {
4244*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4245*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
4246*61046927SAndroid Build Coastguard Worker 
4247*61046927SAndroid Build Coastguard Worker     if (g.NavId == 0 || g.NavDisableHighlight || g.NavId != window->DC.LastItemId)
4248*61046927SAndroid Build Coastguard Worker         return false;
4249*61046927SAndroid Build Coastguard Worker     return true;
4250*61046927SAndroid Build Coastguard Worker }
4251*61046927SAndroid Build Coastguard Worker 
IsItemClicked(int mouse_button)4252*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemClicked(int mouse_button)
4253*61046927SAndroid Build Coastguard Worker {
4254*61046927SAndroid Build Coastguard Worker     return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
4255*61046927SAndroid Build Coastguard Worker }
4256*61046927SAndroid Build Coastguard Worker 
IsAnyItemHovered()4257*61046927SAndroid Build Coastguard Worker bool ImGui::IsAnyItemHovered()
4258*61046927SAndroid Build Coastguard Worker {
4259*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4260*61046927SAndroid Build Coastguard Worker     return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0;
4261*61046927SAndroid Build Coastguard Worker }
4262*61046927SAndroid Build Coastguard Worker 
IsAnyItemActive()4263*61046927SAndroid Build Coastguard Worker bool ImGui::IsAnyItemActive()
4264*61046927SAndroid Build Coastguard Worker {
4265*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4266*61046927SAndroid Build Coastguard Worker     return g.ActiveId != 0;
4267*61046927SAndroid Build Coastguard Worker }
4268*61046927SAndroid Build Coastguard Worker 
IsAnyItemFocused()4269*61046927SAndroid Build Coastguard Worker bool ImGui::IsAnyItemFocused()
4270*61046927SAndroid Build Coastguard Worker {
4271*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4272*61046927SAndroid Build Coastguard Worker     return g.NavId != 0 && !g.NavDisableHighlight;
4273*61046927SAndroid Build Coastguard Worker }
4274*61046927SAndroid Build Coastguard Worker 
IsItemVisible()4275*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemVisible()
4276*61046927SAndroid Build Coastguard Worker {
4277*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
4278*61046927SAndroid Build Coastguard Worker     return window->ClipRect.Overlaps(window->DC.LastItemRect);
4279*61046927SAndroid Build Coastguard Worker }
4280*61046927SAndroid Build Coastguard Worker 
IsItemEdited()4281*61046927SAndroid Build Coastguard Worker bool ImGui::IsItemEdited()
4282*61046927SAndroid Build Coastguard Worker {
4283*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
4284*61046927SAndroid Build Coastguard Worker     return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0;
4285*61046927SAndroid Build Coastguard Worker }
4286*61046927SAndroid Build Coastguard Worker 
4287*61046927SAndroid Build Coastguard Worker // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
SetItemAllowOverlap()4288*61046927SAndroid Build Coastguard Worker void ImGui::SetItemAllowOverlap()
4289*61046927SAndroid Build Coastguard Worker {
4290*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4291*61046927SAndroid Build Coastguard Worker     if (g.HoveredId == g.CurrentWindow->DC.LastItemId)
4292*61046927SAndroid Build Coastguard Worker         g.HoveredIdAllowOverlap = true;
4293*61046927SAndroid Build Coastguard Worker     if (g.ActiveId == g.CurrentWindow->DC.LastItemId)
4294*61046927SAndroid Build Coastguard Worker         g.ActiveIdAllowOverlap = true;
4295*61046927SAndroid Build Coastguard Worker }
4296*61046927SAndroid Build Coastguard Worker 
GetItemRectMin()4297*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetItemRectMin()
4298*61046927SAndroid Build Coastguard Worker {
4299*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
4300*61046927SAndroid Build Coastguard Worker     return window->DC.LastItemRect.Min;
4301*61046927SAndroid Build Coastguard Worker }
4302*61046927SAndroid Build Coastguard Worker 
GetItemRectMax()4303*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetItemRectMax()
4304*61046927SAndroid Build Coastguard Worker {
4305*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
4306*61046927SAndroid Build Coastguard Worker     return window->DC.LastItemRect.Max;
4307*61046927SAndroid Build Coastguard Worker }
4308*61046927SAndroid Build Coastguard Worker 
GetItemRectSize()4309*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetItemRectSize()
4310*61046927SAndroid Build Coastguard Worker {
4311*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
4312*61046927SAndroid Build Coastguard Worker     return window->DC.LastItemRect.GetSize();
4313*61046927SAndroid Build Coastguard Worker }
4314*61046927SAndroid Build Coastguard Worker 
GetViewportRect()4315*61046927SAndroid Build Coastguard Worker static ImRect GetViewportRect()
4316*61046927SAndroid Build Coastguard Worker {
4317*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4318*61046927SAndroid Build Coastguard Worker     return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
4319*61046927SAndroid Build Coastguard Worker }
4320*61046927SAndroid Build Coastguard Worker 
BeginChildEx(const char * name,ImGuiID id,const ImVec2 & size_arg,bool border,ImGuiWindowFlags flags)4321*61046927SAndroid Build Coastguard Worker static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
4322*61046927SAndroid Build Coastguard Worker {
4323*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4324*61046927SAndroid Build Coastguard Worker     ImGuiWindow* parent_window = g.CurrentWindow;
4325*61046927SAndroid Build Coastguard Worker 
4326*61046927SAndroid Build Coastguard Worker     flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
4327*61046927SAndroid Build Coastguard Worker     flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);  // Inherit the NoMove flag
4328*61046927SAndroid Build Coastguard Worker 
4329*61046927SAndroid Build Coastguard Worker     // Size
4330*61046927SAndroid Build Coastguard Worker     const ImVec2 content_avail = GetContentRegionAvail();
4331*61046927SAndroid Build Coastguard Worker     ImVec2 size = ImFloor(size_arg);
4332*61046927SAndroid Build Coastguard Worker     const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
4333*61046927SAndroid Build Coastguard Worker     if (size.x <= 0.0f)
4334*61046927SAndroid Build Coastguard Worker         size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues)
4335*61046927SAndroid Build Coastguard Worker     if (size.y <= 0.0f)
4336*61046927SAndroid Build Coastguard Worker         size.y = ImMax(content_avail.y + size.y, 4.0f);
4337*61046927SAndroid Build Coastguard Worker     SetNextWindowSize(size);
4338*61046927SAndroid Build Coastguard Worker 
4339*61046927SAndroid Build Coastguard Worker     // 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.
4340*61046927SAndroid Build Coastguard Worker     char title[256];
4341*61046927SAndroid Build Coastguard Worker     if (name)
4342*61046927SAndroid Build Coastguard Worker         ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s_%08X", parent_window->Name, name, id);
4343*61046927SAndroid Build Coastguard Worker     else
4344*61046927SAndroid Build Coastguard Worker         ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id);
4345*61046927SAndroid Build Coastguard Worker 
4346*61046927SAndroid Build Coastguard Worker     const float backup_border_size = g.Style.ChildBorderSize;
4347*61046927SAndroid Build Coastguard Worker     if (!border)
4348*61046927SAndroid Build Coastguard Worker         g.Style.ChildBorderSize = 0.0f;
4349*61046927SAndroid Build Coastguard Worker     bool ret = Begin(title, NULL, flags);
4350*61046927SAndroid Build Coastguard Worker     g.Style.ChildBorderSize = backup_border_size;
4351*61046927SAndroid Build Coastguard Worker 
4352*61046927SAndroid Build Coastguard Worker     ImGuiWindow* child_window = g.CurrentWindow;
4353*61046927SAndroid Build Coastguard Worker     child_window->ChildId = id;
4354*61046927SAndroid Build Coastguard Worker     child_window->AutoFitChildAxises = auto_fit_axises;
4355*61046927SAndroid Build Coastguard Worker 
4356*61046927SAndroid Build Coastguard Worker     // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
4357*61046927SAndroid Build Coastguard Worker     // While this is not really documented/defined, it seems that the expected thing to do.
4358*61046927SAndroid Build Coastguard Worker     if (child_window->BeginCount == 1)
4359*61046927SAndroid Build Coastguard Worker         parent_window->DC.CursorPos = child_window->Pos;
4360*61046927SAndroid Build Coastguard Worker 
4361*61046927SAndroid Build Coastguard Worker     // Process navigation-in immediately so NavInit can run on first frame
4362*61046927SAndroid Build Coastguard Worker     if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll))
4363*61046927SAndroid Build Coastguard Worker     {
4364*61046927SAndroid Build Coastguard Worker         FocusWindow(child_window);
4365*61046927SAndroid Build Coastguard Worker         NavInitWindow(child_window, false);
4366*61046927SAndroid Build Coastguard Worker         SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
4367*61046927SAndroid Build Coastguard Worker         g.ActiveIdSource = ImGuiInputSource_Nav;
4368*61046927SAndroid Build Coastguard Worker     }
4369*61046927SAndroid Build Coastguard Worker     return ret;
4370*61046927SAndroid Build Coastguard Worker }
4371*61046927SAndroid Build Coastguard Worker 
BeginChild(const char * str_id,const ImVec2 & size_arg,bool border,ImGuiWindowFlags extra_flags)4372*61046927SAndroid Build Coastguard Worker bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
4373*61046927SAndroid Build Coastguard Worker {
4374*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
4375*61046927SAndroid Build Coastguard Worker     return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
4376*61046927SAndroid Build Coastguard Worker }
4377*61046927SAndroid Build Coastguard Worker 
BeginChild(ImGuiID id,const ImVec2 & size_arg,bool border,ImGuiWindowFlags extra_flags)4378*61046927SAndroid Build Coastguard Worker bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
4379*61046927SAndroid Build Coastguard Worker {
4380*61046927SAndroid Build Coastguard Worker     IM_ASSERT(id != 0);
4381*61046927SAndroid Build Coastguard Worker     return BeginChildEx(NULL, id, size_arg, border, extra_flags);
4382*61046927SAndroid Build Coastguard Worker }
4383*61046927SAndroid Build Coastguard Worker 
EndChild()4384*61046927SAndroid Build Coastguard Worker void ImGui::EndChild()
4385*61046927SAndroid Build Coastguard Worker {
4386*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4387*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
4388*61046927SAndroid Build Coastguard Worker 
4389*61046927SAndroid Build Coastguard Worker     IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);   // Mismatched BeginChild()/EndChild() callss
4390*61046927SAndroid Build Coastguard Worker     if (window->BeginCount > 1)
4391*61046927SAndroid Build Coastguard Worker     {
4392*61046927SAndroid Build Coastguard Worker         End();
4393*61046927SAndroid Build Coastguard Worker     }
4394*61046927SAndroid Build Coastguard Worker     else
4395*61046927SAndroid Build Coastguard Worker     {
4396*61046927SAndroid Build Coastguard Worker         ImVec2 sz = window->Size;
4397*61046927SAndroid Build Coastguard Worker         if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
4398*61046927SAndroid Build Coastguard Worker             sz.x = ImMax(4.0f, sz.x);
4399*61046927SAndroid Build Coastguard Worker         if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
4400*61046927SAndroid Build Coastguard Worker             sz.y = ImMax(4.0f, sz.y);
4401*61046927SAndroid Build Coastguard Worker         End();
4402*61046927SAndroid Build Coastguard Worker 
4403*61046927SAndroid Build Coastguard Worker         ImGuiWindow* parent_window = g.CurrentWindow;
4404*61046927SAndroid Build Coastguard Worker         ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
4405*61046927SAndroid Build Coastguard Worker         ItemSize(sz);
4406*61046927SAndroid Build Coastguard Worker         if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
4407*61046927SAndroid Build Coastguard Worker         {
4408*61046927SAndroid Build Coastguard Worker             ItemAdd(bb, window->ChildId);
4409*61046927SAndroid Build Coastguard Worker             RenderNavHighlight(bb, window->ChildId);
4410*61046927SAndroid Build Coastguard Worker 
4411*61046927SAndroid Build Coastguard Worker             // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
4412*61046927SAndroid Build Coastguard Worker             if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow)
4413*61046927SAndroid Build Coastguard Worker                 RenderNavHighlight(ImRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
4414*61046927SAndroid Build Coastguard Worker         }
4415*61046927SAndroid Build Coastguard Worker         else
4416*61046927SAndroid Build Coastguard Worker         {
4417*61046927SAndroid Build Coastguard Worker             // Not navigable into
4418*61046927SAndroid Build Coastguard Worker             ItemAdd(bb, 0);
4419*61046927SAndroid Build Coastguard Worker         }
4420*61046927SAndroid Build Coastguard Worker     }
4421*61046927SAndroid Build Coastguard Worker }
4422*61046927SAndroid Build Coastguard Worker 
4423*61046927SAndroid Build Coastguard Worker // Helper to create a child window / scrolling region that looks like a normal widget frame.
BeginChildFrame(ImGuiID id,const ImVec2 & size,ImGuiWindowFlags extra_flags)4424*61046927SAndroid Build Coastguard Worker bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
4425*61046927SAndroid Build Coastguard Worker {
4426*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4427*61046927SAndroid Build Coastguard Worker     const ImGuiStyle& style = g.Style;
4428*61046927SAndroid Build Coastguard Worker     PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
4429*61046927SAndroid Build Coastguard Worker     PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
4430*61046927SAndroid Build Coastguard Worker     PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
4431*61046927SAndroid Build Coastguard Worker     PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
4432*61046927SAndroid Build Coastguard Worker     bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
4433*61046927SAndroid Build Coastguard Worker     PopStyleVar(3);
4434*61046927SAndroid Build Coastguard Worker     PopStyleColor();
4435*61046927SAndroid Build Coastguard Worker     return ret;
4436*61046927SAndroid Build Coastguard Worker }
4437*61046927SAndroid Build Coastguard Worker 
EndChildFrame()4438*61046927SAndroid Build Coastguard Worker void ImGui::EndChildFrame()
4439*61046927SAndroid Build Coastguard Worker {
4440*61046927SAndroid Build Coastguard Worker     EndChild();
4441*61046927SAndroid Build Coastguard Worker }
4442*61046927SAndroid Build Coastguard Worker 
4443*61046927SAndroid Build Coastguard Worker // Save and compare stack sizes on Begin()/End() to detect usage errors
CheckStacksSize(ImGuiWindow * window,bool write)4444*61046927SAndroid Build Coastguard Worker static void CheckStacksSize(ImGuiWindow* window, bool write)
4445*61046927SAndroid Build Coastguard Worker {
4446*61046927SAndroid Build Coastguard Worker     // 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)
4447*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4448*61046927SAndroid Build Coastguard Worker     short* p_backup = &window->DC.StackSizesBackup[0];
4449*61046927SAndroid Build Coastguard Worker     { 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()
4450*61046927SAndroid Build Coastguard Worker     { 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()
4451*61046927SAndroid Build Coastguard Worker     { 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()
4452*61046927SAndroid Build Coastguard Worker     // 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.
4453*61046927SAndroid Build Coastguard Worker     { 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()
4454*61046927SAndroid Build Coastguard Worker     { 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()
4455*61046927SAndroid Build Coastguard Worker     { 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()
4456*61046927SAndroid Build Coastguard Worker     IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
4457*61046927SAndroid Build Coastguard Worker }
4458*61046927SAndroid Build Coastguard Worker 
SetWindowConditionAllowFlags(ImGuiWindow * window,ImGuiCond flags,bool enabled)4459*61046927SAndroid Build Coastguard Worker static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
4460*61046927SAndroid Build Coastguard Worker {
4461*61046927SAndroid Build Coastguard Worker     window->SetWindowPosAllowFlags       = enabled ? (window->SetWindowPosAllowFlags       | flags) : (window->SetWindowPosAllowFlags       & ~flags);
4462*61046927SAndroid Build Coastguard Worker     window->SetWindowSizeAllowFlags      = enabled ? (window->SetWindowSizeAllowFlags      | flags) : (window->SetWindowSizeAllowFlags      & ~flags);
4463*61046927SAndroid Build Coastguard Worker     window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
4464*61046927SAndroid Build Coastguard Worker }
4465*61046927SAndroid Build Coastguard Worker 
FindWindowByID(ImGuiID id)4466*61046927SAndroid Build Coastguard Worker ImGuiWindow* ImGui::FindWindowByID(ImGuiID id)
4467*61046927SAndroid Build Coastguard Worker {
4468*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4469*61046927SAndroid Build Coastguard Worker     return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id);
4470*61046927SAndroid Build Coastguard Worker }
4471*61046927SAndroid Build Coastguard Worker 
FindWindowByName(const char * name)4472*61046927SAndroid Build Coastguard Worker ImGuiWindow* ImGui::FindWindowByName(const char* name)
4473*61046927SAndroid Build Coastguard Worker {
4474*61046927SAndroid Build Coastguard Worker     ImGuiID id = ImHashStr(name, 0);
4475*61046927SAndroid Build Coastguard Worker     return FindWindowByID(id);
4476*61046927SAndroid Build Coastguard Worker }
4477*61046927SAndroid Build Coastguard Worker 
CreateNewWindow(const char * name,ImVec2 size,ImGuiWindowFlags flags)4478*61046927SAndroid Build Coastguard Worker static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
4479*61046927SAndroid Build Coastguard Worker {
4480*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4481*61046927SAndroid Build Coastguard Worker 
4482*61046927SAndroid Build Coastguard Worker     // Create window the first time
4483*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
4484*61046927SAndroid Build Coastguard Worker     window->Flags = flags;
4485*61046927SAndroid Build Coastguard Worker     g.WindowsById.SetVoidPtr(window->ID, window);
4486*61046927SAndroid Build Coastguard Worker 
4487*61046927SAndroid Build Coastguard Worker     // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
4488*61046927SAndroid Build Coastguard Worker     window->Pos = ImVec2(60, 60);
4489*61046927SAndroid Build Coastguard Worker 
4490*61046927SAndroid Build Coastguard Worker     // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
4491*61046927SAndroid Build Coastguard Worker     if (!(flags & ImGuiWindowFlags_NoSavedSettings))
4492*61046927SAndroid Build Coastguard Worker         if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
4493*61046927SAndroid Build Coastguard Worker         {
4494*61046927SAndroid Build Coastguard Worker             // Retrieve settings from .ini file
4495*61046927SAndroid Build Coastguard Worker             window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
4496*61046927SAndroid Build Coastguard Worker             SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
4497*61046927SAndroid Build Coastguard Worker             window->Pos = ImFloor(settings->Pos);
4498*61046927SAndroid Build Coastguard Worker             window->Collapsed = settings->Collapsed;
4499*61046927SAndroid Build Coastguard Worker             if (ImLengthSqr(settings->Size) > 0.00001f)
4500*61046927SAndroid Build Coastguard Worker                 size = ImFloor(settings->Size);
4501*61046927SAndroid Build Coastguard Worker         }
4502*61046927SAndroid Build Coastguard Worker     window->Size = window->SizeFull = window->SizeFullAtLastBegin = ImFloor(size);
4503*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
4504*61046927SAndroid Build Coastguard Worker 
4505*61046927SAndroid Build Coastguard Worker     if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
4506*61046927SAndroid Build Coastguard Worker     {
4507*61046927SAndroid Build Coastguard Worker         window->AutoFitFramesX = window->AutoFitFramesY = 2;
4508*61046927SAndroid Build Coastguard Worker         window->AutoFitOnlyGrows = false;
4509*61046927SAndroid Build Coastguard Worker     }
4510*61046927SAndroid Build Coastguard Worker     else
4511*61046927SAndroid Build Coastguard Worker     {
4512*61046927SAndroid Build Coastguard Worker         if (window->Size.x <= 0.0f)
4513*61046927SAndroid Build Coastguard Worker             window->AutoFitFramesX = 2;
4514*61046927SAndroid Build Coastguard Worker         if (window->Size.y <= 0.0f)
4515*61046927SAndroid Build Coastguard Worker             window->AutoFitFramesY = 2;
4516*61046927SAndroid Build Coastguard Worker         window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
4517*61046927SAndroid Build Coastguard Worker     }
4518*61046927SAndroid Build Coastguard Worker 
4519*61046927SAndroid Build Coastguard Worker     g.WindowsFocusOrder.push_back(window);
4520*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
4521*61046927SAndroid Build Coastguard Worker         g.Windows.push_front(window); // Quite slow but rare and only once
4522*61046927SAndroid Build Coastguard Worker     else
4523*61046927SAndroid Build Coastguard Worker         g.Windows.push_back(window);
4524*61046927SAndroid Build Coastguard Worker     return window;
4525*61046927SAndroid Build Coastguard Worker }
4526*61046927SAndroid Build Coastguard Worker 
CalcSizeAfterConstraint(ImGuiWindow * window,ImVec2 new_size)4527*61046927SAndroid Build Coastguard Worker static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
4528*61046927SAndroid Build Coastguard Worker {
4529*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4530*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.SizeConstraintCond != 0)
4531*61046927SAndroid Build Coastguard Worker     {
4532*61046927SAndroid Build Coastguard Worker         // Using -1,-1 on either X/Y axis to preserve the current size.
4533*61046927SAndroid Build Coastguard Worker         ImRect cr = g.NextWindowData.SizeConstraintRect;
4534*61046927SAndroid Build Coastguard Worker         new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
4535*61046927SAndroid Build Coastguard Worker         new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
4536*61046927SAndroid Build Coastguard Worker         if (g.NextWindowData.SizeCallback)
4537*61046927SAndroid Build Coastguard Worker         {
4538*61046927SAndroid Build Coastguard Worker             ImGuiSizeCallbackData data;
4539*61046927SAndroid Build Coastguard Worker             data.UserData = g.NextWindowData.SizeCallbackUserData;
4540*61046927SAndroid Build Coastguard Worker             data.Pos = window->Pos;
4541*61046927SAndroid Build Coastguard Worker             data.CurrentSize = window->SizeFull;
4542*61046927SAndroid Build Coastguard Worker             data.DesiredSize = new_size;
4543*61046927SAndroid Build Coastguard Worker             g.NextWindowData.SizeCallback(&data);
4544*61046927SAndroid Build Coastguard Worker             new_size = data.DesiredSize;
4545*61046927SAndroid Build Coastguard Worker         }
4546*61046927SAndroid Build Coastguard Worker     }
4547*61046927SAndroid Build Coastguard Worker 
4548*61046927SAndroid Build Coastguard Worker     // Minimum size
4549*61046927SAndroid Build Coastguard Worker     if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
4550*61046927SAndroid Build Coastguard Worker     {
4551*61046927SAndroid Build Coastguard Worker         new_size = ImMax(new_size, g.Style.WindowMinSize);
4552*61046927SAndroid Build Coastguard Worker         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
4553*61046927SAndroid Build Coastguard Worker     }
4554*61046927SAndroid Build Coastguard Worker     return new_size;
4555*61046927SAndroid Build Coastguard Worker }
4556*61046927SAndroid Build Coastguard Worker 
CalcSizeContents(ImGuiWindow * window)4557*61046927SAndroid Build Coastguard Worker static ImVec2 CalcSizeContents(ImGuiWindow* window)
4558*61046927SAndroid Build Coastguard Worker {
4559*61046927SAndroid Build Coastguard Worker     if (window->Collapsed)
4560*61046927SAndroid Build Coastguard Worker         if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
4561*61046927SAndroid Build Coastguard Worker             return window->SizeContents;
4562*61046927SAndroid Build Coastguard Worker     if (window->Hidden && window->HiddenFramesForResize == 0 && window->HiddenFramesRegular > 0)
4563*61046927SAndroid Build Coastguard Worker         return window->SizeContents;
4564*61046927SAndroid Build Coastguard Worker 
4565*61046927SAndroid Build Coastguard Worker     ImVec2 sz;
4566*61046927SAndroid Build Coastguard Worker     sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
4567*61046927SAndroid Build Coastguard Worker     sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
4568*61046927SAndroid Build Coastguard Worker     return sz + window->WindowPadding;
4569*61046927SAndroid Build Coastguard Worker }
4570*61046927SAndroid Build Coastguard Worker 
CalcSizeAutoFit(ImGuiWindow * window,const ImVec2 & size_contents)4571*61046927SAndroid Build Coastguard Worker static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
4572*61046927SAndroid Build Coastguard Worker {
4573*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4574*61046927SAndroid Build Coastguard Worker     ImGuiStyle& style = g.Style;
4575*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Tooltip)
4576*61046927SAndroid Build Coastguard Worker     {
4577*61046927SAndroid Build Coastguard Worker         // Tooltip always resize
4578*61046927SAndroid Build Coastguard Worker         return size_contents;
4579*61046927SAndroid Build Coastguard Worker     }
4580*61046927SAndroid Build Coastguard Worker     else
4581*61046927SAndroid Build Coastguard Worker     {
4582*61046927SAndroid Build Coastguard Worker         // Maximum window size is determined by the display size
4583*61046927SAndroid Build Coastguard Worker         const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0;
4584*61046927SAndroid Build Coastguard Worker         const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
4585*61046927SAndroid Build Coastguard Worker         ImVec2 size_min = style.WindowMinSize;
4586*61046927SAndroid Build Coastguard Worker         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)
4587*61046927SAndroid Build Coastguard Worker             size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
4588*61046927SAndroid Build Coastguard Worker         ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
4589*61046927SAndroid Build Coastguard Worker 
4590*61046927SAndroid Build Coastguard Worker         // When the window cannot fit all contents (either because of constraints, either because screen is too small),
4591*61046927SAndroid Build Coastguard Worker         // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
4592*61046927SAndroid Build Coastguard Worker         ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
4593*61046927SAndroid Build Coastguard Worker         if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
4594*61046927SAndroid Build Coastguard Worker             size_auto_fit.y += style.ScrollbarSize;
4595*61046927SAndroid Build Coastguard Worker         if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
4596*61046927SAndroid Build Coastguard Worker             size_auto_fit.x += style.ScrollbarSize;
4597*61046927SAndroid Build Coastguard Worker         return size_auto_fit;
4598*61046927SAndroid Build Coastguard Worker     }
4599*61046927SAndroid Build Coastguard Worker }
4600*61046927SAndroid Build Coastguard Worker 
CalcWindowExpectedSize(ImGuiWindow * window)4601*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window)
4602*61046927SAndroid Build Coastguard Worker {
4603*61046927SAndroid Build Coastguard Worker     ImVec2 size_contents = CalcSizeContents(window);
4604*61046927SAndroid Build Coastguard Worker     return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents));
4605*61046927SAndroid Build Coastguard Worker }
4606*61046927SAndroid Build Coastguard Worker 
GetWindowScrollMaxX(ImGuiWindow * window)4607*61046927SAndroid Build Coastguard Worker float ImGui::GetWindowScrollMaxX(ImGuiWindow* window)
4608*61046927SAndroid Build Coastguard Worker {
4609*61046927SAndroid Build Coastguard Worker     return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
4610*61046927SAndroid Build Coastguard Worker }
4611*61046927SAndroid Build Coastguard Worker 
GetWindowScrollMaxY(ImGuiWindow * window)4612*61046927SAndroid Build Coastguard Worker float ImGui::GetWindowScrollMaxY(ImGuiWindow* window)
4613*61046927SAndroid Build Coastguard Worker {
4614*61046927SAndroid Build Coastguard Worker     return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
4615*61046927SAndroid Build Coastguard Worker }
4616*61046927SAndroid Build Coastguard Worker 
CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow * window,bool snap_on_edges)4617*61046927SAndroid Build Coastguard Worker static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
4618*61046927SAndroid Build Coastguard Worker {
4619*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4620*61046927SAndroid Build Coastguard Worker     ImVec2 scroll = window->Scroll;
4621*61046927SAndroid Build Coastguard Worker     if (window->ScrollTarget.x < FLT_MAX)
4622*61046927SAndroid Build Coastguard Worker     {
4623*61046927SAndroid Build Coastguard Worker         float cr_x = window->ScrollTargetCenterRatio.x;
4624*61046927SAndroid Build Coastguard Worker         scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
4625*61046927SAndroid Build Coastguard Worker     }
4626*61046927SAndroid Build Coastguard Worker     if (window->ScrollTarget.y < FLT_MAX)
4627*61046927SAndroid Build Coastguard Worker     {
4628*61046927SAndroid Build Coastguard Worker         // '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.
4629*61046927SAndroid Build Coastguard Worker         float cr_y = window->ScrollTargetCenterRatio.y;
4630*61046927SAndroid Build Coastguard Worker         float target_y = window->ScrollTarget.y;
4631*61046927SAndroid Build Coastguard Worker         if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y)
4632*61046927SAndroid Build Coastguard Worker             target_y = 0.0f;
4633*61046927SAndroid Build Coastguard Worker         if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y)
4634*61046927SAndroid Build Coastguard Worker             target_y = window->SizeContents.y;
4635*61046927SAndroid Build Coastguard Worker         scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);
4636*61046927SAndroid Build Coastguard Worker     }
4637*61046927SAndroid Build Coastguard Worker     scroll = ImMax(scroll, ImVec2(0.0f, 0.0f));
4638*61046927SAndroid Build Coastguard Worker     if (!window->Collapsed && !window->SkipItems)
4639*61046927SAndroid Build Coastguard Worker     {
4640*61046927SAndroid Build Coastguard Worker         scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window));
4641*61046927SAndroid Build Coastguard Worker         scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window));
4642*61046927SAndroid Build Coastguard Worker     }
4643*61046927SAndroid Build Coastguard Worker     return scroll;
4644*61046927SAndroid Build Coastguard Worker }
4645*61046927SAndroid Build Coastguard Worker 
GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)4646*61046927SAndroid Build Coastguard Worker static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)
4647*61046927SAndroid Build Coastguard Worker {
4648*61046927SAndroid Build Coastguard Worker     if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
4649*61046927SAndroid Build Coastguard Worker         return ImGuiCol_PopupBg;
4650*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_ChildWindow)
4651*61046927SAndroid Build Coastguard Worker         return ImGuiCol_ChildBg;
4652*61046927SAndroid Build Coastguard Worker     return ImGuiCol_WindowBg;
4653*61046927SAndroid Build Coastguard Worker }
4654*61046927SAndroid Build Coastguard Worker 
CalcResizePosSizeFromAnyCorner(ImGuiWindow * window,const ImVec2 & corner_target,const ImVec2 & corner_norm,ImVec2 * out_pos,ImVec2 * out_size)4655*61046927SAndroid Build Coastguard Worker static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
4656*61046927SAndroid Build Coastguard Worker {
4657*61046927SAndroid Build Coastguard Worker     ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm);                // Expected window upper-left
4658*61046927SAndroid Build Coastguard Worker     ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
4659*61046927SAndroid Build Coastguard Worker     ImVec2 size_expected = pos_max - pos_min;
4660*61046927SAndroid Build Coastguard Worker     ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected);
4661*61046927SAndroid Build Coastguard Worker     *out_pos = pos_min;
4662*61046927SAndroid Build Coastguard Worker     if (corner_norm.x == 0.0f)
4663*61046927SAndroid Build Coastguard Worker         out_pos->x -= (size_constrained.x - size_expected.x);
4664*61046927SAndroid Build Coastguard Worker     if (corner_norm.y == 0.0f)
4665*61046927SAndroid Build Coastguard Worker         out_pos->y -= (size_constrained.y - size_expected.y);
4666*61046927SAndroid Build Coastguard Worker     *out_size = size_constrained;
4667*61046927SAndroid Build Coastguard Worker }
4668*61046927SAndroid Build Coastguard Worker 
4669*61046927SAndroid Build Coastguard Worker struct ImGuiResizeGripDef
4670*61046927SAndroid Build Coastguard Worker {
4671*61046927SAndroid Build Coastguard Worker     ImVec2  CornerPosN;
4672*61046927SAndroid Build Coastguard Worker     ImVec2  InnerDir;
4673*61046927SAndroid Build Coastguard Worker     int     AngleMin12, AngleMax12;
4674*61046927SAndroid Build Coastguard Worker };
4675*61046927SAndroid Build Coastguard Worker 
4676*61046927SAndroid Build Coastguard Worker static const ImGuiResizeGripDef resize_grip_def[4] =
4677*61046927SAndroid Build Coastguard Worker {
4678*61046927SAndroid Build Coastguard Worker     { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower right
4679*61046927SAndroid Build Coastguard Worker     { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower left
4680*61046927SAndroid Build Coastguard Worker     { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper left
4681*61046927SAndroid Build Coastguard Worker     { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right
4682*61046927SAndroid Build Coastguard Worker };
4683*61046927SAndroid Build Coastguard Worker 
GetResizeBorderRect(ImGuiWindow * window,int border_n,float perp_padding,float thickness)4684*61046927SAndroid Build Coastguard Worker static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
4685*61046927SAndroid Build Coastguard Worker {
4686*61046927SAndroid Build Coastguard Worker     ImRect rect = window->Rect();
4687*61046927SAndroid Build Coastguard Worker     if (thickness == 0.0f) rect.Max -= ImVec2(1,1);
4688*61046927SAndroid Build Coastguard Worker     if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness,    rect.Max.x - perp_padding, rect.Min.y + thickness);      // Top
4689*61046927SAndroid Build Coastguard Worker     if (border_n == 1) return ImRect(rect.Max.x - thickness,    rect.Min.y + perp_padding, rect.Max.x + thickness,    rect.Max.y - perp_padding);   // Right
4690*61046927SAndroid Build Coastguard Worker     if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness,    rect.Max.x - perp_padding, rect.Max.y + thickness);      // Bottom
4691*61046927SAndroid Build Coastguard Worker     if (border_n == 3) return ImRect(rect.Min.x - thickness,    rect.Min.y + perp_padding, rect.Min.x + thickness,    rect.Max.y - perp_padding);   // Left
4692*61046927SAndroid Build Coastguard Worker     IM_ASSERT(0);
4693*61046927SAndroid Build Coastguard Worker     return ImRect();
4694*61046927SAndroid Build Coastguard Worker }
4695*61046927SAndroid Build Coastguard Worker 
4696*61046927SAndroid Build Coastguard Worker // Handle resize for: Resize Grips, Borders, Gamepad
UpdateManualResize(ImGuiWindow * window,const ImVec2 & size_auto_fit,int * border_held,int resize_grip_count,ImU32 resize_grip_col[4])4697*61046927SAndroid Build Coastguard Worker static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
4698*61046927SAndroid Build Coastguard Worker {
4699*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4700*61046927SAndroid Build Coastguard Worker     ImGuiWindowFlags flags = window->Flags;
4701*61046927SAndroid Build Coastguard Worker     if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
4702*61046927SAndroid Build Coastguard Worker         return;
4703*61046927SAndroid Build Coastguard Worker     if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
4704*61046927SAndroid Build Coastguard Worker         return;
4705*61046927SAndroid Build Coastguard Worker 
4706*61046927SAndroid Build Coastguard Worker     const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
4707*61046927SAndroid Build Coastguard Worker     const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
4708*61046927SAndroid Build Coastguard Worker     const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f);
4709*61046927SAndroid Build Coastguard Worker     const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f;
4710*61046927SAndroid Build Coastguard Worker 
4711*61046927SAndroid Build Coastguard Worker     ImVec2 pos_target(FLT_MAX, FLT_MAX);
4712*61046927SAndroid Build Coastguard Worker     ImVec2 size_target(FLT_MAX, FLT_MAX);
4713*61046927SAndroid Build Coastguard Worker 
4714*61046927SAndroid Build Coastguard Worker     // Manual resize grips
4715*61046927SAndroid Build Coastguard Worker     PushID("#RESIZE");
4716*61046927SAndroid Build Coastguard Worker     for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
4717*61046927SAndroid Build Coastguard Worker     {
4718*61046927SAndroid Build Coastguard Worker         const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
4719*61046927SAndroid Build Coastguard Worker         const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
4720*61046927SAndroid Build Coastguard Worker 
4721*61046927SAndroid Build Coastguard Worker         // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
4722*61046927SAndroid Build Coastguard Worker         ImRect resize_rect(corner - grip.InnerDir * grip_hover_outer_size, corner + grip.InnerDir * grip_hover_inner_size);
4723*61046927SAndroid Build Coastguard Worker         if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
4724*61046927SAndroid Build Coastguard Worker         if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
4725*61046927SAndroid Build Coastguard Worker         bool hovered, held;
4726*61046927SAndroid Build Coastguard Worker         ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
4727*61046927SAndroid Build Coastguard Worker         //GetOverlayDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
4728*61046927SAndroid Build Coastguard Worker         if (hovered || held)
4729*61046927SAndroid Build Coastguard Worker             g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
4730*61046927SAndroid Build Coastguard Worker 
4731*61046927SAndroid Build Coastguard Worker         if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
4732*61046927SAndroid Build Coastguard Worker         {
4733*61046927SAndroid Build Coastguard Worker             // Manual auto-fit when double-clicking
4734*61046927SAndroid Build Coastguard Worker             size_target = CalcSizeAfterConstraint(window, size_auto_fit);
4735*61046927SAndroid Build Coastguard Worker             ClearActiveID();
4736*61046927SAndroid Build Coastguard Worker         }
4737*61046927SAndroid Build Coastguard Worker         else if (held)
4738*61046927SAndroid Build Coastguard Worker         {
4739*61046927SAndroid Build Coastguard Worker             // Resize from any of the four corners
4740*61046927SAndroid Build Coastguard Worker             // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
4741*61046927SAndroid Build Coastguard Worker             ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPosN); // Corner of the window corresponding to our corner grip
4742*61046927SAndroid Build Coastguard Worker             CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPosN, &pos_target, &size_target);
4743*61046927SAndroid Build Coastguard Worker         }
4744*61046927SAndroid Build Coastguard Worker         if (resize_grip_n == 0 || held || hovered)
4745*61046927SAndroid Build Coastguard Worker             resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
4746*61046927SAndroid Build Coastguard Worker     }
4747*61046927SAndroid Build Coastguard Worker     for (int border_n = 0; border_n < resize_border_count; border_n++)
4748*61046927SAndroid Build Coastguard Worker     {
4749*61046927SAndroid Build Coastguard Worker         bool hovered, held;
4750*61046927SAndroid Build Coastguard Worker         ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS);
4751*61046927SAndroid Build Coastguard Worker         ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
4752*61046927SAndroid Build Coastguard Worker         //GetOverlayDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
4753*61046927SAndroid Build Coastguard Worker         if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
4754*61046927SAndroid Build Coastguard Worker         {
4755*61046927SAndroid Build Coastguard Worker             g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
4756*61046927SAndroid Build Coastguard Worker             if (held)
4757*61046927SAndroid Build Coastguard Worker                 *border_held = border_n;
4758*61046927SAndroid Build Coastguard Worker         }
4759*61046927SAndroid Build Coastguard Worker         if (held)
4760*61046927SAndroid Build Coastguard Worker         {
4761*61046927SAndroid Build Coastguard Worker             ImVec2 border_target = window->Pos;
4762*61046927SAndroid Build Coastguard Worker             ImVec2 border_posn;
4763*61046927SAndroid Build Coastguard Worker             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); } // Top
4764*61046927SAndroid Build Coastguard Worker             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); } // Right
4765*61046927SAndroid Build Coastguard Worker             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); } // Bottom
4766*61046927SAndroid Build Coastguard Worker             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); } // Left
4767*61046927SAndroid Build Coastguard Worker             CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
4768*61046927SAndroid Build Coastguard Worker         }
4769*61046927SAndroid Build Coastguard Worker     }
4770*61046927SAndroid Build Coastguard Worker     PopID();
4771*61046927SAndroid Build Coastguard Worker 
4772*61046927SAndroid Build Coastguard Worker     // Navigation resize (keyboard/gamepad)
4773*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
4774*61046927SAndroid Build Coastguard Worker     {
4775*61046927SAndroid Build Coastguard Worker         ImVec2 nav_resize_delta;
4776*61046927SAndroid Build Coastguard Worker         if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift)
4777*61046927SAndroid Build Coastguard Worker             nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
4778*61046927SAndroid Build Coastguard Worker         if (g.NavInputSource == ImGuiInputSource_NavGamepad)
4779*61046927SAndroid Build Coastguard Worker             nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down);
4780*61046927SAndroid Build Coastguard Worker         if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
4781*61046927SAndroid Build Coastguard Worker         {
4782*61046927SAndroid Build Coastguard Worker             const float NAV_RESIZE_SPEED = 600.0f;
4783*61046927SAndroid Build Coastguard Worker             nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
4784*61046927SAndroid Build Coastguard Worker             g.NavWindowingToggleLayer = false;
4785*61046927SAndroid Build Coastguard Worker             g.NavDisableMouseHover = true;
4786*61046927SAndroid Build Coastguard Worker             resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
4787*61046927SAndroid Build Coastguard Worker             // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
4788*61046927SAndroid Build Coastguard Worker             size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
4789*61046927SAndroid Build Coastguard Worker         }
4790*61046927SAndroid Build Coastguard Worker     }
4791*61046927SAndroid Build Coastguard Worker 
4792*61046927SAndroid Build Coastguard Worker     // Apply back modified position/size to window
4793*61046927SAndroid Build Coastguard Worker     if (size_target.x != FLT_MAX)
4794*61046927SAndroid Build Coastguard Worker     {
4795*61046927SAndroid Build Coastguard Worker         window->SizeFull = size_target;
4796*61046927SAndroid Build Coastguard Worker         MarkIniSettingsDirty(window);
4797*61046927SAndroid Build Coastguard Worker     }
4798*61046927SAndroid Build Coastguard Worker     if (pos_target.x != FLT_MAX)
4799*61046927SAndroid Build Coastguard Worker     {
4800*61046927SAndroid Build Coastguard Worker         window->Pos = ImFloor(pos_target);
4801*61046927SAndroid Build Coastguard Worker         MarkIniSettingsDirty(window);
4802*61046927SAndroid Build Coastguard Worker     }
4803*61046927SAndroid Build Coastguard Worker 
4804*61046927SAndroid Build Coastguard Worker     window->Size = window->SizeFull;
4805*61046927SAndroid Build Coastguard Worker }
4806*61046927SAndroid Build Coastguard Worker 
RenderOuterBorders(ImGuiWindow * window)4807*61046927SAndroid Build Coastguard Worker static void ImGui::RenderOuterBorders(ImGuiWindow* window)
4808*61046927SAndroid Build Coastguard Worker {
4809*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4810*61046927SAndroid Build Coastguard Worker     float rounding = window->WindowRounding;
4811*61046927SAndroid Build Coastguard Worker     float border_size = window->WindowBorderSize;
4812*61046927SAndroid Build Coastguard Worker     if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
4813*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
4814*61046927SAndroid Build Coastguard Worker 
4815*61046927SAndroid Build Coastguard Worker     int border_held = window->ResizeBorderHeld;
4816*61046927SAndroid Build Coastguard Worker     if (border_held != -1)
4817*61046927SAndroid Build Coastguard Worker     {
4818*61046927SAndroid Build Coastguard Worker         struct ImGuiResizeBorderDef
4819*61046927SAndroid Build Coastguard Worker         {
4820*61046927SAndroid Build Coastguard Worker             ImVec2 InnerDir;
4821*61046927SAndroid Build Coastguard Worker             ImVec2 CornerPosN1, CornerPosN2;
4822*61046927SAndroid Build Coastguard Worker             float  OuterAngle;
4823*61046927SAndroid Build Coastguard Worker         };
4824*61046927SAndroid Build Coastguard Worker         static const ImGuiResizeBorderDef resize_border_def[4] =
4825*61046927SAndroid Build Coastguard Worker         {
4826*61046927SAndroid Build Coastguard Worker             { ImVec2(0,+1), ImVec2(0,0), ImVec2(1,0), IM_PI*1.50f }, // Top
4827*61046927SAndroid Build Coastguard Worker             { ImVec2(-1,0), ImVec2(1,0), ImVec2(1,1), IM_PI*0.00f }, // Right
4828*61046927SAndroid Build Coastguard Worker             { ImVec2(0,-1), ImVec2(1,1), ImVec2(0,1), IM_PI*0.50f }, // Bottom
4829*61046927SAndroid Build Coastguard Worker             { ImVec2(+1,0), ImVec2(0,1), ImVec2(0,0), IM_PI*1.00f }  // Left
4830*61046927SAndroid Build Coastguard Worker         };
4831*61046927SAndroid Build Coastguard Worker         const ImGuiResizeBorderDef& def = resize_border_def[border_held];
4832*61046927SAndroid Build Coastguard Worker         ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
4833*61046927SAndroid Build Coastguard Worker         window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI*0.25f, def.OuterAngle);
4834*61046927SAndroid Build Coastguard Worker         window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI*0.25f);
4835*61046927SAndroid Build Coastguard Worker         window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), false, ImMax(2.0f, border_size)); // Thicker than usual
4836*61046927SAndroid Build Coastguard Worker     }
4837*61046927SAndroid Build Coastguard Worker     if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
4838*61046927SAndroid Build Coastguard Worker     {
4839*61046927SAndroid Build Coastguard Worker         float y = window->Pos.y + window->TitleBarHeight() - 1;
4840*61046927SAndroid Build Coastguard Worker         window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize);
4841*61046927SAndroid Build Coastguard Worker     }
4842*61046927SAndroid Build Coastguard Worker }
4843*61046927SAndroid Build Coastguard Worker 
UpdateWindowParentAndRootLinks(ImGuiWindow * window,ImGuiWindowFlags flags,ImGuiWindow * parent_window)4844*61046927SAndroid Build Coastguard Worker void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
4845*61046927SAndroid Build Coastguard Worker {
4846*61046927SAndroid Build Coastguard Worker     window->ParentWindow = parent_window;
4847*61046927SAndroid Build Coastguard Worker     window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
4848*61046927SAndroid Build Coastguard Worker     if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
4849*61046927SAndroid Build Coastguard Worker         window->RootWindow = parent_window->RootWindow;
4850*61046927SAndroid Build Coastguard Worker     if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
4851*61046927SAndroid Build Coastguard Worker         window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
4852*61046927SAndroid Build Coastguard Worker     while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
4853*61046927SAndroid Build Coastguard Worker     {
4854*61046927SAndroid Build Coastguard Worker         IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
4855*61046927SAndroid Build Coastguard Worker         window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
4856*61046927SAndroid Build Coastguard Worker     }
4857*61046927SAndroid Build Coastguard Worker }
4858*61046927SAndroid Build Coastguard Worker 
4859*61046927SAndroid Build Coastguard Worker // Push a new ImGui window to add widgets to.
4860*61046927SAndroid Build Coastguard Worker // - 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.
4861*61046927SAndroid Build Coastguard Worker // - Begin/End can be called multiple times during the frame with the same window name to append content.
4862*61046927SAndroid Build Coastguard Worker // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
4863*61046927SAndroid Build Coastguard Worker //   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.
4864*61046927SAndroid Build Coastguard Worker // - 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.
4865*61046927SAndroid Build Coastguard Worker // - 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.
Begin(const char * name,bool * p_open,ImGuiWindowFlags flags)4866*61046927SAndroid Build Coastguard Worker bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
4867*61046927SAndroid Build Coastguard Worker {
4868*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
4869*61046927SAndroid Build Coastguard Worker     const ImGuiStyle& style = g.Style;
4870*61046927SAndroid Build Coastguard Worker     IM_ASSERT(name != NULL && name[0] != '\0');     // Window name required
4871*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.FrameScopeActive);                  // Forgot to call ImGui::NewFrame()
4872*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
4873*61046927SAndroid Build Coastguard Worker 
4874*61046927SAndroid Build Coastguard Worker     // Find or create
4875*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = FindWindowByName(name);
4876*61046927SAndroid Build Coastguard Worker     const bool window_just_created = (window == NULL);
4877*61046927SAndroid Build Coastguard Worker     if (window_just_created)
4878*61046927SAndroid Build Coastguard Worker     {
4879*61046927SAndroid Build Coastguard Worker         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.
4880*61046927SAndroid Build Coastguard Worker         window = CreateNewWindow(name, size_on_first_use, flags);
4881*61046927SAndroid Build Coastguard Worker     }
4882*61046927SAndroid Build Coastguard Worker 
4883*61046927SAndroid Build Coastguard Worker     // Automatically disable manual moving/resizing when NoInputs is set
4884*61046927SAndroid Build Coastguard Worker     if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
4885*61046927SAndroid Build Coastguard Worker         flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
4886*61046927SAndroid Build Coastguard Worker 
4887*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_NavFlattened)
4888*61046927SAndroid Build Coastguard Worker         IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
4889*61046927SAndroid Build Coastguard Worker 
4890*61046927SAndroid Build Coastguard Worker     const int current_frame = g.FrameCount;
4891*61046927SAndroid Build Coastguard Worker     const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
4892*61046927SAndroid Build Coastguard Worker 
4893*61046927SAndroid Build Coastguard Worker     // Update Flags, LastFrameActive, BeginOrderXXX fields
4894*61046927SAndroid Build Coastguard Worker     if (first_begin_of_the_frame)
4895*61046927SAndroid Build Coastguard Worker         window->Flags = (ImGuiWindowFlags)flags;
4896*61046927SAndroid Build Coastguard Worker     else
4897*61046927SAndroid Build Coastguard Worker         flags = window->Flags;
4898*61046927SAndroid Build Coastguard Worker 
4899*61046927SAndroid Build Coastguard Worker     // 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
4900*61046927SAndroid Build Coastguard Worker     ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
4901*61046927SAndroid Build Coastguard Worker     ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
4902*61046927SAndroid Build Coastguard Worker     IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
4903*61046927SAndroid Build Coastguard Worker     window->HasCloseButton = (p_open != NULL);
4904*61046927SAndroid Build Coastguard Worker 
4905*61046927SAndroid Build Coastguard Worker     // Update the Appearing flag
4906*61046927SAndroid Build Coastguard Worker     bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1);   // Not using !WasActive because the implicit "Debug" window would always toggle off->on
4907*61046927SAndroid Build Coastguard Worker     const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0);
4908*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_Popup)
4909*61046927SAndroid Build Coastguard Worker     {
4910*61046927SAndroid Build Coastguard Worker         ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
4911*61046927SAndroid Build Coastguard Worker         window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
4912*61046927SAndroid Build Coastguard Worker         window_just_activated_by_user |= (window != popup_ref.Window);
4913*61046927SAndroid Build Coastguard Worker     }
4914*61046927SAndroid Build Coastguard Worker     window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize);
4915*61046927SAndroid Build Coastguard Worker     if (window->Appearing)
4916*61046927SAndroid Build Coastguard Worker         SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true);
4917*61046927SAndroid Build Coastguard Worker 
4918*61046927SAndroid Build Coastguard Worker     // Add to stack
4919*61046927SAndroid Build Coastguard Worker     g.CurrentWindowStack.push_back(window);
4920*61046927SAndroid Build Coastguard Worker     SetCurrentWindow(window);
4921*61046927SAndroid Build Coastguard Worker     CheckStacksSize(window, true);
4922*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_Popup)
4923*61046927SAndroid Build Coastguard Worker     {
4924*61046927SAndroid Build Coastguard Worker         ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
4925*61046927SAndroid Build Coastguard Worker         popup_ref.Window = window;
4926*61046927SAndroid Build Coastguard Worker         g.BeginPopupStack.push_back(popup_ref);
4927*61046927SAndroid Build Coastguard Worker         window->PopupId = popup_ref.PopupId;
4928*61046927SAndroid Build Coastguard Worker     }
4929*61046927SAndroid Build Coastguard Worker 
4930*61046927SAndroid Build Coastguard Worker     if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow))
4931*61046927SAndroid Build Coastguard Worker         window->NavLastIds[0] = 0;
4932*61046927SAndroid Build Coastguard Worker 
4933*61046927SAndroid Build Coastguard Worker     // Process SetNextWindow***() calls
4934*61046927SAndroid Build Coastguard Worker     bool window_pos_set_by_api = false;
4935*61046927SAndroid Build Coastguard Worker     bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
4936*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.PosCond)
4937*61046927SAndroid Build Coastguard Worker     {
4938*61046927SAndroid Build Coastguard Worker         window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
4939*61046927SAndroid Build Coastguard Worker         if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
4940*61046927SAndroid Build Coastguard Worker         {
4941*61046927SAndroid Build Coastguard Worker             // May be processed on the next frame if this is our first frame and we are measuring size
4942*61046927SAndroid Build Coastguard Worker             // FIXME: Look into removing the branch so everything can go through this same code path for consistency.
4943*61046927SAndroid Build Coastguard Worker             window->SetWindowPosVal = g.NextWindowData.PosVal;
4944*61046927SAndroid Build Coastguard Worker             window->SetWindowPosPivot = g.NextWindowData.PosPivotVal;
4945*61046927SAndroid Build Coastguard Worker             window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
4946*61046927SAndroid Build Coastguard Worker         }
4947*61046927SAndroid Build Coastguard Worker         else
4948*61046927SAndroid Build Coastguard Worker         {
4949*61046927SAndroid Build Coastguard Worker             SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
4950*61046927SAndroid Build Coastguard Worker         }
4951*61046927SAndroid Build Coastguard Worker     }
4952*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.SizeCond)
4953*61046927SAndroid Build Coastguard Worker     {
4954*61046927SAndroid Build Coastguard Worker         window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
4955*61046927SAndroid Build Coastguard Worker         window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
4956*61046927SAndroid Build Coastguard Worker         SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
4957*61046927SAndroid Build Coastguard Worker     }
4958*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.ContentSizeCond)
4959*61046927SAndroid Build Coastguard Worker     {
4960*61046927SAndroid Build Coastguard Worker         // Adjust passed "client size" to become a "window size"
4961*61046927SAndroid Build Coastguard Worker         window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
4962*61046927SAndroid Build Coastguard Worker         if (window->SizeContentsExplicit.y != 0.0f)
4963*61046927SAndroid Build Coastguard Worker             window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight();
4964*61046927SAndroid Build Coastguard Worker     }
4965*61046927SAndroid Build Coastguard Worker     else if (first_begin_of_the_frame)
4966*61046927SAndroid Build Coastguard Worker     {
4967*61046927SAndroid Build Coastguard Worker         window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
4968*61046927SAndroid Build Coastguard Worker     }
4969*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.CollapsedCond)
4970*61046927SAndroid Build Coastguard Worker         SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
4971*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.FocusCond)
4972*61046927SAndroid Build Coastguard Worker         FocusWindow(window);
4973*61046927SAndroid Build Coastguard Worker     if (window->Appearing)
4974*61046927SAndroid Build Coastguard Worker         SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
4975*61046927SAndroid Build Coastguard Worker 
4976*61046927SAndroid Build Coastguard Worker     // When reusing window again multiple times a frame, just append content (don't need to setup again)
4977*61046927SAndroid Build Coastguard Worker     if (first_begin_of_the_frame)
4978*61046927SAndroid Build Coastguard Worker     {
4979*61046927SAndroid Build Coastguard Worker         // Initialize
4980*61046927SAndroid Build Coastguard Worker         const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
4981*61046927SAndroid Build Coastguard Worker         UpdateWindowParentAndRootLinks(window, flags, parent_window);
4982*61046927SAndroid Build Coastguard Worker 
4983*61046927SAndroid Build Coastguard Worker         window->Active = true;
4984*61046927SAndroid Build Coastguard Worker         window->BeginOrderWithinParent = 0;
4985*61046927SAndroid Build Coastguard Worker         window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
4986*61046927SAndroid Build Coastguard Worker         window->BeginCount = 0;
4987*61046927SAndroid Build Coastguard Worker         window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
4988*61046927SAndroid Build Coastguard Worker         window->LastFrameActive = current_frame;
4989*61046927SAndroid Build Coastguard Worker         window->IDStack.resize(1);
4990*61046927SAndroid Build Coastguard Worker 
4991*61046927SAndroid Build Coastguard Worker         // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged).
4992*61046927SAndroid Build Coastguard Worker         // 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.
4993*61046927SAndroid Build Coastguard Worker         bool window_title_visible_elsewhere = false;
4994*61046927SAndroid Build Coastguard Worker         if (g.NavWindowingList != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0)   // Window titles visible when using CTRL+TAB
4995*61046927SAndroid Build Coastguard Worker             window_title_visible_elsewhere = true;
4996*61046927SAndroid Build Coastguard Worker         if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
4997*61046927SAndroid Build Coastguard Worker         {
4998*61046927SAndroid Build Coastguard Worker             size_t buf_len = (size_t)window->NameBufLen;
4999*61046927SAndroid Build Coastguard Worker             window->Name = ImStrdupcpy(window->Name, &buf_len, name);
5000*61046927SAndroid Build Coastguard Worker             window->NameBufLen = (int)buf_len;
5001*61046927SAndroid Build Coastguard Worker         }
5002*61046927SAndroid Build Coastguard Worker 
5003*61046927SAndroid Build Coastguard Worker         // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
5004*61046927SAndroid Build Coastguard Worker 
5005*61046927SAndroid Build Coastguard Worker         // Update contents size from last frame for auto-fitting (or use explicit size)
5006*61046927SAndroid Build Coastguard Worker         window->SizeContents = CalcSizeContents(window);
5007*61046927SAndroid Build Coastguard Worker         if (window->HiddenFramesRegular > 0)
5008*61046927SAndroid Build Coastguard Worker             window->HiddenFramesRegular--;
5009*61046927SAndroid Build Coastguard Worker         if (window->HiddenFramesForResize > 0)
5010*61046927SAndroid Build Coastguard Worker             window->HiddenFramesForResize--;
5011*61046927SAndroid Build Coastguard Worker 
5012*61046927SAndroid Build Coastguard Worker         // Hide new windows for one frame until they calculate their size
5013*61046927SAndroid Build Coastguard Worker         if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
5014*61046927SAndroid Build Coastguard Worker             window->HiddenFramesForResize = 1;
5015*61046927SAndroid Build Coastguard Worker 
5016*61046927SAndroid Build Coastguard Worker         // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
5017*61046927SAndroid Build Coastguard Worker         // We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
5018*61046927SAndroid Build Coastguard Worker         if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
5019*61046927SAndroid Build Coastguard Worker         {
5020*61046927SAndroid Build Coastguard Worker             window->HiddenFramesForResize = 1;
5021*61046927SAndroid Build Coastguard Worker             if (flags & ImGuiWindowFlags_AlwaysAutoResize)
5022*61046927SAndroid Build Coastguard Worker             {
5023*61046927SAndroid Build Coastguard Worker                 if (!window_size_x_set_by_api)
5024*61046927SAndroid Build Coastguard Worker                     window->Size.x = window->SizeFull.x = 0.f;
5025*61046927SAndroid Build Coastguard Worker                 if (!window_size_y_set_by_api)
5026*61046927SAndroid Build Coastguard Worker                     window->Size.y = window->SizeFull.y = 0.f;
5027*61046927SAndroid Build Coastguard Worker                 window->SizeContents = ImVec2(0.f, 0.f);
5028*61046927SAndroid Build Coastguard Worker             }
5029*61046927SAndroid Build Coastguard Worker         }
5030*61046927SAndroid Build Coastguard Worker 
5031*61046927SAndroid Build Coastguard Worker         SetCurrentWindow(window);
5032*61046927SAndroid Build Coastguard Worker 
5033*61046927SAndroid Build Coastguard Worker         // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies)
5034*61046927SAndroid Build Coastguard Worker         window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
5035*61046927SAndroid Build Coastguard Worker         window->WindowPadding = style.WindowPadding;
5036*61046927SAndroid Build Coastguard Worker         if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
5037*61046927SAndroid Build Coastguard Worker             window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
5038*61046927SAndroid Build Coastguard Worker         window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
5039*61046927SAndroid Build Coastguard Worker         window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
5040*61046927SAndroid Build Coastguard Worker 
5041*61046927SAndroid Build Coastguard Worker         // Collapse window by double-clicking on title bar
5042*61046927SAndroid Build Coastguard Worker         // 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
5043*61046927SAndroid Build Coastguard Worker         if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
5044*61046927SAndroid Build Coastguard Worker         {
5045*61046927SAndroid Build Coastguard Worker             // 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.
5046*61046927SAndroid Build Coastguard Worker             ImRect title_bar_rect = window->TitleBarRect();
5047*61046927SAndroid Build Coastguard Worker             if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])
5048*61046927SAndroid Build Coastguard Worker                 window->WantCollapseToggle = true;
5049*61046927SAndroid Build Coastguard Worker             if (window->WantCollapseToggle)
5050*61046927SAndroid Build Coastguard Worker             {
5051*61046927SAndroid Build Coastguard Worker                 window->Collapsed = !window->Collapsed;
5052*61046927SAndroid Build Coastguard Worker                 MarkIniSettingsDirty(window);
5053*61046927SAndroid Build Coastguard Worker                 FocusWindow(window);
5054*61046927SAndroid Build Coastguard Worker             }
5055*61046927SAndroid Build Coastguard Worker         }
5056*61046927SAndroid Build Coastguard Worker         else
5057*61046927SAndroid Build Coastguard Worker         {
5058*61046927SAndroid Build Coastguard Worker             window->Collapsed = false;
5059*61046927SAndroid Build Coastguard Worker         }
5060*61046927SAndroid Build Coastguard Worker         window->WantCollapseToggle = false;
5061*61046927SAndroid Build Coastguard Worker 
5062*61046927SAndroid Build Coastguard Worker         // SIZE
5063*61046927SAndroid Build Coastguard Worker 
5064*61046927SAndroid Build Coastguard Worker         // Calculate auto-fit size, handle automatic resize
5065*61046927SAndroid Build Coastguard Worker         const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
5066*61046927SAndroid Build Coastguard Worker         ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
5067*61046927SAndroid Build Coastguard Worker         if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
5068*61046927SAndroid Build Coastguard Worker         {
5069*61046927SAndroid Build Coastguard Worker             // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
5070*61046927SAndroid Build Coastguard Worker             if (!window_size_x_set_by_api)
5071*61046927SAndroid Build Coastguard Worker                 window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
5072*61046927SAndroid Build Coastguard Worker             if (!window_size_y_set_by_api)
5073*61046927SAndroid Build Coastguard Worker                 window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
5074*61046927SAndroid Build Coastguard Worker         }
5075*61046927SAndroid Build Coastguard Worker         else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
5076*61046927SAndroid Build Coastguard Worker         {
5077*61046927SAndroid Build Coastguard Worker             // Auto-fit may only grow window during the first few frames
5078*61046927SAndroid Build Coastguard Worker             // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
5079*61046927SAndroid Build Coastguard Worker             if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
5080*61046927SAndroid Build Coastguard Worker                 window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
5081*61046927SAndroid Build Coastguard Worker             if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
5082*61046927SAndroid Build Coastguard Worker                 window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
5083*61046927SAndroid Build Coastguard Worker             if (!window->Collapsed)
5084*61046927SAndroid Build Coastguard Worker                 MarkIniSettingsDirty(window);
5085*61046927SAndroid Build Coastguard Worker         }
5086*61046927SAndroid Build Coastguard Worker 
5087*61046927SAndroid Build Coastguard Worker         // Apply minimum/maximum window size constraints and final size
5088*61046927SAndroid Build Coastguard Worker         window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
5089*61046927SAndroid Build Coastguard Worker         window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
5090*61046927SAndroid Build Coastguard Worker 
5091*61046927SAndroid Build Coastguard Worker         // SCROLLBAR STATUS
5092*61046927SAndroid Build Coastguard Worker 
5093*61046927SAndroid Build Coastguard Worker         // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size).
5094*61046927SAndroid Build Coastguard Worker         if (!window->Collapsed)
5095*61046927SAndroid Build Coastguard Worker         {
5096*61046927SAndroid Build Coastguard Worker             // When reading the current size we need to read it after size constraints have been applied
5097*61046927SAndroid Build Coastguard Worker             float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
5098*61046927SAndroid Build Coastguard Worker             float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
5099*61046927SAndroid Build Coastguard Worker             window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
5100*61046927SAndroid Build Coastguard Worker             window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
5101*61046927SAndroid Build Coastguard Worker             if (window->ScrollbarX && !window->ScrollbarY)
5102*61046927SAndroid Build Coastguard Worker                 window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
5103*61046927SAndroid Build Coastguard Worker             window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
5104*61046927SAndroid Build Coastguard Worker         }
5105*61046927SAndroid Build Coastguard Worker 
5106*61046927SAndroid Build Coastguard Worker         // POSITION
5107*61046927SAndroid Build Coastguard Worker 
5108*61046927SAndroid Build Coastguard Worker         // Popup latch its initial position, will position itself when it appears next frame
5109*61046927SAndroid Build Coastguard Worker         if (window_just_activated_by_user)
5110*61046927SAndroid Build Coastguard Worker         {
5111*61046927SAndroid Build Coastguard Worker             window->AutoPosLastDirection = ImGuiDir_None;
5112*61046927SAndroid Build Coastguard Worker             if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
5113*61046927SAndroid Build Coastguard Worker                 window->Pos = g.BeginPopupStack.back().OpenPopupPos;
5114*61046927SAndroid Build Coastguard Worker         }
5115*61046927SAndroid Build Coastguard Worker 
5116*61046927SAndroid Build Coastguard Worker         // Position child window
5117*61046927SAndroid Build Coastguard Worker         if (flags & ImGuiWindowFlags_ChildWindow)
5118*61046927SAndroid Build Coastguard Worker         {
5119*61046927SAndroid Build Coastguard Worker             IM_ASSERT(parent_window && parent_window->Active);
5120*61046927SAndroid Build Coastguard Worker             window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
5121*61046927SAndroid Build Coastguard Worker             parent_window->DC.ChildWindows.push_back(window);
5122*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
5123*61046927SAndroid Build Coastguard Worker                 window->Pos = parent_window->DC.CursorPos;
5124*61046927SAndroid Build Coastguard Worker         }
5125*61046927SAndroid Build Coastguard Worker 
5126*61046927SAndroid Build Coastguard Worker         const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0);
5127*61046927SAndroid Build Coastguard Worker         if (window_pos_with_pivot)
5128*61046927SAndroid Build Coastguard Worker             SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering)
5129*61046927SAndroid Build Coastguard Worker         else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
5130*61046927SAndroid Build Coastguard Worker             window->Pos = FindBestWindowPosForPopup(window);
5131*61046927SAndroid Build Coastguard Worker         else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
5132*61046927SAndroid Build Coastguard Worker             window->Pos = FindBestWindowPosForPopup(window);
5133*61046927SAndroid Build Coastguard Worker         else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
5134*61046927SAndroid Build Coastguard Worker             window->Pos = FindBestWindowPosForPopup(window);
5135*61046927SAndroid Build Coastguard Worker 
5136*61046927SAndroid Build Coastguard Worker         // Clamp position so it stays visible
5137*61046927SAndroid Build Coastguard Worker         // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
5138*61046927SAndroid Build Coastguard Worker         if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
5139*61046927SAndroid Build Coastguard Worker         {
5140*61046927SAndroid Build Coastguard Worker             if (g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
5141*61046927SAndroid Build Coastguard Worker             {
5142*61046927SAndroid Build Coastguard Worker                 ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
5143*61046927SAndroid Build Coastguard Worker                 ImVec2 size_for_clamping = ((g.IO.ConfigWindowsMoveFromTitleBarOnly) && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size;
5144*61046927SAndroid Build Coastguard Worker                 window->Pos = ImMax(window->Pos + size_for_clamping, padding) - size_for_clamping;
5145*61046927SAndroid Build Coastguard Worker                 window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding);
5146*61046927SAndroid Build Coastguard Worker             }
5147*61046927SAndroid Build Coastguard Worker         }
5148*61046927SAndroid Build Coastguard Worker         window->Pos = ImFloor(window->Pos);
5149*61046927SAndroid Build Coastguard Worker 
5150*61046927SAndroid Build Coastguard Worker         // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
5151*61046927SAndroid Build Coastguard Worker         window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
5152*61046927SAndroid Build Coastguard Worker 
5153*61046927SAndroid Build Coastguard Worker         // Prepare for item focus requests
5154*61046927SAndroid Build Coastguard Worker         window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
5155*61046927SAndroid Build Coastguard Worker         window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
5156*61046927SAndroid Build Coastguard Worker         window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
5157*61046927SAndroid Build Coastguard Worker         window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
5158*61046927SAndroid Build Coastguard Worker 
5159*61046927SAndroid Build Coastguard Worker         // Apply scrolling
5160*61046927SAndroid Build Coastguard Worker         window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
5161*61046927SAndroid Build Coastguard Worker         window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
5162*61046927SAndroid Build Coastguard Worker 
5163*61046927SAndroid Build Coastguard Worker         // Apply window focus (new and reactivated windows are moved to front)
5164*61046927SAndroid Build Coastguard Worker         bool want_focus = false;
5165*61046927SAndroid Build Coastguard Worker         if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
5166*61046927SAndroid Build Coastguard Worker         {
5167*61046927SAndroid Build Coastguard Worker             if (flags & ImGuiWindowFlags_Popup)
5168*61046927SAndroid Build Coastguard Worker                 want_focus = true;
5169*61046927SAndroid Build Coastguard Worker             else if ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0)
5170*61046927SAndroid Build Coastguard Worker                 want_focus = true;
5171*61046927SAndroid Build Coastguard Worker         }
5172*61046927SAndroid Build Coastguard Worker 
5173*61046927SAndroid Build Coastguard Worker         // Handle manual resize: Resize Grips, Borders, Gamepad
5174*61046927SAndroid Build Coastguard Worker         int border_held = -1;
5175*61046927SAndroid Build Coastguard Worker         ImU32 resize_grip_col[4] = { 0 };
5176*61046927SAndroid Build Coastguard Worker         const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
5177*61046927SAndroid Build Coastguard Worker         const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
5178*61046927SAndroid Build Coastguard Worker         if (!window->Collapsed)
5179*61046927SAndroid Build Coastguard Worker             UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
5180*61046927SAndroid Build Coastguard Worker         window->ResizeBorderHeld = (signed char)border_held;
5181*61046927SAndroid Build Coastguard Worker 
5182*61046927SAndroid Build Coastguard Worker         // Default item width. Make it proportional to window size if window manually resizes
5183*61046927SAndroid Build Coastguard Worker         if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
5184*61046927SAndroid Build Coastguard Worker             window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
5185*61046927SAndroid Build Coastguard Worker         else
5186*61046927SAndroid Build Coastguard Worker             window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
5187*61046927SAndroid Build Coastguard Worker 
5188*61046927SAndroid Build Coastguard Worker         // DRAWING
5189*61046927SAndroid Build Coastguard Worker 
5190*61046927SAndroid Build Coastguard Worker         // Setup draw list and outer clipping rectangle
5191*61046927SAndroid Build Coastguard Worker         window->DrawList->Clear();
5192*61046927SAndroid Build Coastguard Worker         window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
5193*61046927SAndroid Build Coastguard Worker         window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
5194*61046927SAndroid Build Coastguard Worker         ImRect viewport_rect(GetViewportRect());
5195*61046927SAndroid Build Coastguard Worker         if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
5196*61046927SAndroid Build Coastguard Worker             PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
5197*61046927SAndroid Build Coastguard Worker         else
5198*61046927SAndroid Build Coastguard Worker             PushClipRect(viewport_rect.Min, viewport_rect.Max, true);
5199*61046927SAndroid Build Coastguard Worker 
5200*61046927SAndroid Build Coastguard Worker         // Draw modal window background (darkens what is behind them, all viewports)
5201*61046927SAndroid Build Coastguard Worker         const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0;
5202*61046927SAndroid Build Coastguard Worker         const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
5203*61046927SAndroid Build Coastguard Worker         if (dim_bg_for_modal || dim_bg_for_window_list)
5204*61046927SAndroid Build Coastguard Worker         {
5205*61046927SAndroid Build Coastguard Worker             const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
5206*61046927SAndroid Build Coastguard Worker             window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
5207*61046927SAndroid Build Coastguard Worker         }
5208*61046927SAndroid Build Coastguard Worker 
5209*61046927SAndroid Build Coastguard Worker         // Draw navigation selection/windowing rectangle background
5210*61046927SAndroid Build Coastguard Worker         if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
5211*61046927SAndroid Build Coastguard Worker         {
5212*61046927SAndroid Build Coastguard Worker             ImRect bb = window->Rect();
5213*61046927SAndroid Build Coastguard Worker             bb.Expand(g.FontSize);
5214*61046927SAndroid Build Coastguard Worker             if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
5215*61046927SAndroid Build Coastguard Worker                 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
5216*61046927SAndroid Build Coastguard Worker         }
5217*61046927SAndroid Build Coastguard Worker 
5218*61046927SAndroid Build Coastguard Worker         // Draw window + handle manual resize
5219*61046927SAndroid Build Coastguard Worker         // As we highlight the title bar when want_focus is set, multiple reappearing windows will have have their title bar highlighted on their reappearing frame.
5220*61046927SAndroid Build Coastguard Worker         const float window_rounding = window->WindowRounding;
5221*61046927SAndroid Build Coastguard Worker         const float window_border_size = window->WindowBorderSize;
5222*61046927SAndroid Build Coastguard Worker         const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
5223*61046927SAndroid Build Coastguard Worker         const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
5224*61046927SAndroid Build Coastguard Worker         const ImRect title_bar_rect = window->TitleBarRect();
5225*61046927SAndroid Build Coastguard Worker         if (window->Collapsed)
5226*61046927SAndroid Build Coastguard Worker         {
5227*61046927SAndroid Build Coastguard Worker             // Title bar only
5228*61046927SAndroid Build Coastguard Worker             float backup_border_size = style.FrameBorderSize;
5229*61046927SAndroid Build Coastguard Worker             g.Style.FrameBorderSize = window->WindowBorderSize;
5230*61046927SAndroid Build Coastguard Worker             ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
5231*61046927SAndroid Build Coastguard Worker             RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
5232*61046927SAndroid Build Coastguard Worker             g.Style.FrameBorderSize = backup_border_size;
5233*61046927SAndroid Build Coastguard Worker         }
5234*61046927SAndroid Build Coastguard Worker         else
5235*61046927SAndroid Build Coastguard Worker         {
5236*61046927SAndroid Build Coastguard Worker             // Window background
5237*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiWindowFlags_NoBackground))
5238*61046927SAndroid Build Coastguard Worker             {
5239*61046927SAndroid Build Coastguard Worker                 ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
5240*61046927SAndroid Build Coastguard Worker                 float alpha = 1.0f;
5241*61046927SAndroid Build Coastguard Worker                 if (g.NextWindowData.BgAlphaCond != 0)
5242*61046927SAndroid Build Coastguard Worker                     alpha = g.NextWindowData.BgAlphaVal;
5243*61046927SAndroid Build Coastguard Worker                 if (alpha != 1.0f)
5244*61046927SAndroid Build Coastguard Worker                     bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
5245*61046927SAndroid Build Coastguard Worker                 window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
5246*61046927SAndroid Build Coastguard Worker             }
5247*61046927SAndroid Build Coastguard Worker             g.NextWindowData.BgAlphaCond = 0;
5248*61046927SAndroid Build Coastguard Worker 
5249*61046927SAndroid Build Coastguard Worker             // Title bar
5250*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiWindowFlags_NoTitleBar))
5251*61046927SAndroid Build Coastguard Worker             {
5252*61046927SAndroid Build Coastguard Worker                 ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
5253*61046927SAndroid Build Coastguard Worker                 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
5254*61046927SAndroid Build Coastguard Worker             }
5255*61046927SAndroid Build Coastguard Worker 
5256*61046927SAndroid Build Coastguard Worker             // Menu bar
5257*61046927SAndroid Build Coastguard Worker             if (flags & ImGuiWindowFlags_MenuBar)
5258*61046927SAndroid Build Coastguard Worker             {
5259*61046927SAndroid Build Coastguard Worker                 ImRect menu_bar_rect = window->MenuBarRect();
5260*61046927SAndroid Build Coastguard Worker                 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.
5261*61046927SAndroid Build Coastguard Worker                 window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
5262*61046927SAndroid Build Coastguard Worker                 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
5263*61046927SAndroid Build Coastguard Worker                     window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
5264*61046927SAndroid Build Coastguard Worker             }
5265*61046927SAndroid Build Coastguard Worker 
5266*61046927SAndroid Build Coastguard Worker             // Scrollbars
5267*61046927SAndroid Build Coastguard Worker             if (window->ScrollbarX)
5268*61046927SAndroid Build Coastguard Worker                 Scrollbar(ImGuiLayoutType_Horizontal);
5269*61046927SAndroid Build Coastguard Worker             if (window->ScrollbarY)
5270*61046927SAndroid Build Coastguard Worker                 Scrollbar(ImGuiLayoutType_Vertical);
5271*61046927SAndroid Build Coastguard Worker 
5272*61046927SAndroid Build Coastguard Worker             // Render resize grips (after their input handling so we don't have a frame of latency)
5273*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiWindowFlags_NoResize))
5274*61046927SAndroid Build Coastguard Worker             {
5275*61046927SAndroid Build Coastguard Worker                 for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
5276*61046927SAndroid Build Coastguard Worker                 {
5277*61046927SAndroid Build Coastguard Worker                     const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
5278*61046927SAndroid Build Coastguard Worker                     const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
5279*61046927SAndroid Build Coastguard Worker                     window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size)));
5280*61046927SAndroid Build Coastguard Worker                     window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size)));
5281*61046927SAndroid Build Coastguard Worker                     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);
5282*61046927SAndroid Build Coastguard Worker                     window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
5283*61046927SAndroid Build Coastguard Worker                 }
5284*61046927SAndroid Build Coastguard Worker             }
5285*61046927SAndroid Build Coastguard Worker 
5286*61046927SAndroid Build Coastguard Worker             // Borders
5287*61046927SAndroid Build Coastguard Worker             RenderOuterBorders(window);
5288*61046927SAndroid Build Coastguard Worker         }
5289*61046927SAndroid Build Coastguard Worker 
5290*61046927SAndroid Build Coastguard Worker         // Draw navigation selection/windowing rectangle border
5291*61046927SAndroid Build Coastguard Worker         if (g.NavWindowingTargetAnim == window)
5292*61046927SAndroid Build Coastguard Worker         {
5293*61046927SAndroid Build Coastguard Worker             float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
5294*61046927SAndroid Build Coastguard Worker             ImRect bb = window->Rect();
5295*61046927SAndroid Build Coastguard Worker             bb.Expand(g.FontSize);
5296*61046927SAndroid Build Coastguard Worker             if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
5297*61046927SAndroid Build Coastguard Worker             {
5298*61046927SAndroid Build Coastguard Worker                 bb.Expand(-g.FontSize - 1.0f);
5299*61046927SAndroid Build Coastguard Worker                 rounding = window->WindowRounding;
5300*61046927SAndroid Build Coastguard Worker             }
5301*61046927SAndroid Build Coastguard Worker             window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f);
5302*61046927SAndroid Build Coastguard Worker         }
5303*61046927SAndroid Build Coastguard Worker 
5304*61046927SAndroid Build Coastguard Worker         // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
5305*61046927SAndroid Build Coastguard Worker         window->SizeFullAtLastBegin = window->SizeFull;
5306*61046927SAndroid Build Coastguard Worker 
5307*61046927SAndroid Build Coastguard Worker         // Update various regions. Variables they depends on are set above in this function.
5308*61046927SAndroid Build Coastguard Worker         // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
5309*61046927SAndroid Build Coastguard Worker         window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
5310*61046927SAndroid Build Coastguard Worker         window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
5311*61046927SAndroid Build Coastguard Worker         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));
5312*61046927SAndroid Build Coastguard Worker         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));
5313*61046927SAndroid Build Coastguard Worker 
5314*61046927SAndroid Build Coastguard Worker         // Setup drawing context
5315*61046927SAndroid Build Coastguard Worker         // (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.)
5316*61046927SAndroid Build Coastguard Worker         window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
5317*61046927SAndroid Build Coastguard Worker         window->DC.GroupOffset.x = 0.0f;
5318*61046927SAndroid Build Coastguard Worker         window->DC.ColumnsOffset.x = 0.0f;
5319*61046927SAndroid Build Coastguard Worker         window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);
5320*61046927SAndroid Build Coastguard Worker         window->DC.CursorPos = window->DC.CursorStartPos;
5321*61046927SAndroid Build Coastguard Worker         window->DC.CursorPosPrevLine = window->DC.CursorPos;
5322*61046927SAndroid Build Coastguard Worker         window->DC.CursorMaxPos = window->DC.CursorStartPos;
5323*61046927SAndroid Build Coastguard Worker         window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
5324*61046927SAndroid Build Coastguard Worker         window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
5325*61046927SAndroid Build Coastguard Worker         window->DC.NavHideHighlightOneFrame = false;
5326*61046927SAndroid Build Coastguard Worker         window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
5327*61046927SAndroid Build Coastguard Worker         window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
5328*61046927SAndroid Build Coastguard Worker         window->DC.NavLayerActiveMaskNext = 0x00;
5329*61046927SAndroid Build Coastguard Worker         window->DC.MenuBarAppending = false;
5330*61046927SAndroid Build Coastguard Worker         window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
5331*61046927SAndroid Build Coastguard Worker         window->DC.ChildWindows.resize(0);
5332*61046927SAndroid Build Coastguard Worker         window->DC.LayoutType = ImGuiLayoutType_Vertical;
5333*61046927SAndroid Build Coastguard Worker         window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
5334*61046927SAndroid Build Coastguard Worker         window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
5335*61046927SAndroid Build Coastguard Worker         window->DC.ItemWidth = window->ItemWidthDefault;
5336*61046927SAndroid Build Coastguard Worker         window->DC.TextWrapPos = -1.0f; // disabled
5337*61046927SAndroid Build Coastguard Worker         window->DC.ItemFlagsStack.resize(0);
5338*61046927SAndroid Build Coastguard Worker         window->DC.ItemWidthStack.resize(0);
5339*61046927SAndroid Build Coastguard Worker         window->DC.TextWrapPosStack.resize(0);
5340*61046927SAndroid Build Coastguard Worker         window->DC.ColumnsSet = NULL;
5341*61046927SAndroid Build Coastguard Worker         window->DC.TreeDepth = 0;
5342*61046927SAndroid Build Coastguard Worker         window->DC.TreeDepthMayJumpToParentOnPop = 0x00;
5343*61046927SAndroid Build Coastguard Worker         window->DC.StateStorage = &window->StateStorage;
5344*61046927SAndroid Build Coastguard Worker         window->DC.GroupStack.resize(0);
5345*61046927SAndroid Build Coastguard Worker         window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
5346*61046927SAndroid Build Coastguard Worker 
5347*61046927SAndroid Build Coastguard Worker         if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags))
5348*61046927SAndroid Build Coastguard Worker         {
5349*61046927SAndroid Build Coastguard Worker             window->DC.ItemFlags = parent_window->DC.ItemFlags;
5350*61046927SAndroid Build Coastguard Worker             window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5351*61046927SAndroid Build Coastguard Worker         }
5352*61046927SAndroid Build Coastguard Worker 
5353*61046927SAndroid Build Coastguard Worker         if (window->AutoFitFramesX > 0)
5354*61046927SAndroid Build Coastguard Worker             window->AutoFitFramesX--;
5355*61046927SAndroid Build Coastguard Worker         if (window->AutoFitFramesY > 0)
5356*61046927SAndroid Build Coastguard Worker             window->AutoFitFramesY--;
5357*61046927SAndroid Build Coastguard Worker 
5358*61046927SAndroid Build Coastguard Worker         // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
5359*61046927SAndroid Build Coastguard Worker         if (want_focus)
5360*61046927SAndroid Build Coastguard Worker         {
5361*61046927SAndroid Build Coastguard Worker             FocusWindow(window);
5362*61046927SAndroid Build Coastguard Worker             NavInitWindow(window, false);
5363*61046927SAndroid Build Coastguard Worker         }
5364*61046927SAndroid Build Coastguard Worker 
5365*61046927SAndroid Build Coastguard Worker         // Title bar
5366*61046927SAndroid Build Coastguard Worker         if (!(flags & ImGuiWindowFlags_NoTitleBar))
5367*61046927SAndroid Build Coastguard Worker         {
5368*61046927SAndroid Build Coastguard Worker             // Close & collapse button are on layer 1 (same as menus) and don't default focus
5369*61046927SAndroid Build Coastguard Worker             const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
5370*61046927SAndroid Build Coastguard Worker             window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
5371*61046927SAndroid Build Coastguard Worker             window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
5372*61046927SAndroid Build Coastguard Worker             window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
5373*61046927SAndroid Build Coastguard Worker 
5374*61046927SAndroid Build Coastguard Worker             // Collapse button
5375*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiWindowFlags_NoCollapse))
5376*61046927SAndroid Build Coastguard Worker                 if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos))
5377*61046927SAndroid Build Coastguard Worker                     window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
5378*61046927SAndroid Build Coastguard Worker 
5379*61046927SAndroid Build Coastguard Worker             // Close button
5380*61046927SAndroid Build Coastguard Worker             if (p_open != NULL)
5381*61046927SAndroid Build Coastguard Worker             {
5382*61046927SAndroid Build Coastguard Worker                 const float pad = style.FramePadding.y;
5383*61046927SAndroid Build Coastguard Worker                 const float rad = g.FontSize * 0.5f;
5384*61046927SAndroid Build Coastguard Worker                 if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1))
5385*61046927SAndroid Build Coastguard Worker                     *p_open = false;
5386*61046927SAndroid Build Coastguard Worker             }
5387*61046927SAndroid Build Coastguard Worker 
5388*61046927SAndroid Build Coastguard Worker             window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
5389*61046927SAndroid Build Coastguard Worker             window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
5390*61046927SAndroid Build Coastguard Worker             window->DC.ItemFlags = item_flags_backup;
5391*61046927SAndroid Build Coastguard Worker 
5392*61046927SAndroid Build Coastguard Worker             // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
5393*61046927SAndroid Build Coastguard Worker             // FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
5394*61046927SAndroid Build Coastguard Worker             const char* UNSAVED_DOCUMENT_MARKER = "*";
5395*61046927SAndroid Build Coastguard Worker             float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
5396*61046927SAndroid Build Coastguard Worker             ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
5397*61046927SAndroid Build Coastguard Worker             ImRect text_r = title_bar_rect;
5398*61046927SAndroid Build Coastguard Worker             float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
5399*61046927SAndroid Build Coastguard Worker             float pad_right = (p_open == NULL)                     ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
5400*61046927SAndroid Build Coastguard Worker             if (style.WindowTitleAlign.x > 0.0f)
5401*61046927SAndroid Build Coastguard Worker                 pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
5402*61046927SAndroid Build Coastguard Worker             text_r.Min.x += pad_left;
5403*61046927SAndroid Build Coastguard Worker             text_r.Max.x -= pad_right;
5404*61046927SAndroid Build Coastguard Worker             ImRect clip_rect = text_r;
5405*61046927SAndroid Build Coastguard Worker             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()
5406*61046927SAndroid Build Coastguard Worker             RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
5407*61046927SAndroid Build Coastguard Worker             if (flags & ImGuiWindowFlags_UnsavedDocument)
5408*61046927SAndroid Build Coastguard Worker             {
5409*61046927SAndroid Build Coastguard Worker                 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);
5410*61046927SAndroid Build Coastguard Worker                 ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
5411*61046927SAndroid Build Coastguard Worker                 RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
5412*61046927SAndroid Build Coastguard Worker             }
5413*61046927SAndroid Build Coastguard Worker         }
5414*61046927SAndroid Build Coastguard Worker 
5415*61046927SAndroid Build Coastguard Worker         // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
5416*61046927SAndroid Build Coastguard Worker         window->OuterRectClipped = window->Rect();
5417*61046927SAndroid Build Coastguard Worker         window->OuterRectClipped.ClipWith(window->ClipRect);
5418*61046927SAndroid Build Coastguard Worker 
5419*61046927SAndroid Build Coastguard Worker         // Pressing CTRL+C while holding on a window copy its content to the clipboard
5420*61046927SAndroid Build Coastguard Worker         // 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.
5421*61046927SAndroid Build Coastguard Worker         // Maybe we can support CTRL+C on every element?
5422*61046927SAndroid Build Coastguard Worker         /*
5423*61046927SAndroid Build Coastguard Worker         if (g.ActiveId == move_id)
5424*61046927SAndroid Build Coastguard Worker             if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
5425*61046927SAndroid Build Coastguard Worker                 LogToClipboard();
5426*61046927SAndroid Build Coastguard Worker         */
5427*61046927SAndroid Build Coastguard Worker 
5428*61046927SAndroid Build Coastguard Worker         // Inner rectangle
5429*61046927SAndroid Build Coastguard Worker         // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
5430*61046927SAndroid Build Coastguard Worker         // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
5431*61046927SAndroid Build Coastguard Worker         window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
5432*61046927SAndroid Build Coastguard Worker         window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
5433*61046927SAndroid Build Coastguard Worker         window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize;
5434*61046927SAndroid Build Coastguard Worker         window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize;
5435*61046927SAndroid Build Coastguard Worker         //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE);
5436*61046927SAndroid Build Coastguard Worker 
5437*61046927SAndroid Build Coastguard Worker         // Inner clipping rectangle
5438*61046927SAndroid Build Coastguard Worker         // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
5439*61046927SAndroid Build Coastguard Worker         window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5440*61046927SAndroid Build Coastguard Worker         window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
5441*61046927SAndroid Build Coastguard Worker         window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5442*61046927SAndroid Build Coastguard Worker         window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
5443*61046927SAndroid Build Coastguard Worker 
5444*61046927SAndroid Build Coastguard Worker         // We fill last item data based on Title Bar, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
5445*61046927SAndroid Build Coastguard Worker         // This is useful to allow creating context menus on title bar only, etc.
5446*61046927SAndroid Build Coastguard Worker         window->DC.LastItemId = window->MoveId;
5447*61046927SAndroid Build Coastguard Worker         window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
5448*61046927SAndroid Build Coastguard Worker         window->DC.LastItemRect = title_bar_rect;
5449*61046927SAndroid Build Coastguard Worker     }
5450*61046927SAndroid Build Coastguard Worker 
5451*61046927SAndroid Build Coastguard Worker     PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
5452*61046927SAndroid Build Coastguard Worker 
5453*61046927SAndroid Build Coastguard Worker     // 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)
5454*61046927SAndroid Build Coastguard Worker     if (first_begin_of_the_frame)
5455*61046927SAndroid Build Coastguard Worker         window->WriteAccessed = false;
5456*61046927SAndroid Build Coastguard Worker 
5457*61046927SAndroid Build Coastguard Worker     window->BeginCount++;
5458*61046927SAndroid Build Coastguard Worker     g.NextWindowData.Clear();
5459*61046927SAndroid Build Coastguard Worker 
5460*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiWindowFlags_ChildWindow)
5461*61046927SAndroid Build Coastguard Worker     {
5462*61046927SAndroid Build Coastguard Worker         // Child window can be out of sight and have "negative" clip windows.
5463*61046927SAndroid Build Coastguard Worker         // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar).
5464*61046927SAndroid Build Coastguard Worker         IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);
5465*61046927SAndroid Build Coastguard Worker         if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
5466*61046927SAndroid Build Coastguard Worker             if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
5467*61046927SAndroid Build Coastguard Worker                 window->HiddenFramesRegular = 1;
5468*61046927SAndroid Build Coastguard Worker 
5469*61046927SAndroid Build Coastguard Worker         // Completely hide along with parent or if parent is collapsed
5470*61046927SAndroid Build Coastguard Worker         if (parent_window && (parent_window->Collapsed || parent_window->Hidden))
5471*61046927SAndroid Build Coastguard Worker             window->HiddenFramesRegular = 1;
5472*61046927SAndroid Build Coastguard Worker     }
5473*61046927SAndroid Build Coastguard Worker 
5474*61046927SAndroid Build Coastguard Worker     // 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)
5475*61046927SAndroid Build Coastguard Worker     if (style.Alpha <= 0.0f)
5476*61046927SAndroid Build Coastguard Worker         window->HiddenFramesRegular = 1;
5477*61046927SAndroid Build Coastguard Worker 
5478*61046927SAndroid Build Coastguard Worker     // Update the Hidden flag
5479*61046927SAndroid Build Coastguard Worker     window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize > 0);
5480*61046927SAndroid Build Coastguard Worker 
5481*61046927SAndroid Build Coastguard Worker     // Return false if we don't intend to display anything to allow user to perform an early out optimization
5482*61046927SAndroid Build Coastguard Worker     window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0;
5483*61046927SAndroid Build Coastguard Worker 
5484*61046927SAndroid Build Coastguard Worker     return !window->SkipItems;
5485*61046927SAndroid Build Coastguard Worker }
5486*61046927SAndroid Build Coastguard Worker 
5487*61046927SAndroid Build Coastguard Worker // Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead.
5488*61046927SAndroid Build Coastguard Worker #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
Begin(const char * name,bool * p_open,const ImVec2 & size_first_use,float bg_alpha_override,ImGuiWindowFlags flags)5489*61046927SAndroid Build Coastguard Worker bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags)
5490*61046927SAndroid Build Coastguard Worker {
5491*61046927SAndroid Build Coastguard Worker     // 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.
5492*61046927SAndroid Build Coastguard Worker     if (size_first_use.x != 0.0f || size_first_use.y != 0.0f)
5493*61046927SAndroid Build Coastguard Worker         SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver);
5494*61046927SAndroid Build Coastguard Worker 
5495*61046927SAndroid Build Coastguard Worker     // Old API feature: override the window background alpha with a parameter.
5496*61046927SAndroid Build Coastguard Worker     if (bg_alpha_override >= 0.0f)
5497*61046927SAndroid Build Coastguard Worker         SetNextWindowBgAlpha(bg_alpha_override);
5498*61046927SAndroid Build Coastguard Worker 
5499*61046927SAndroid Build Coastguard Worker     return Begin(name, p_open, flags);
5500*61046927SAndroid Build Coastguard Worker }
5501*61046927SAndroid Build Coastguard Worker #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5502*61046927SAndroid Build Coastguard Worker 
End()5503*61046927SAndroid Build Coastguard Worker void ImGui::End()
5504*61046927SAndroid Build Coastguard Worker {
5505*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5506*61046927SAndroid Build Coastguard Worker 
5507*61046927SAndroid Build Coastguard Worker     if (g.CurrentWindowStack.Size <= 1 && g.FrameScopePushedImplicitWindow)
5508*61046927SAndroid Build Coastguard Worker     {
5509*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!");
5510*61046927SAndroid Build Coastguard Worker         return; // FIXME-ERRORHANDLING
5511*61046927SAndroid Build Coastguard Worker     }
5512*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.CurrentWindowStack.Size > 0);
5513*61046927SAndroid Build Coastguard Worker 
5514*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
5515*61046927SAndroid Build Coastguard Worker 
5516*61046927SAndroid Build Coastguard Worker     if (window->DC.ColumnsSet != NULL)
5517*61046927SAndroid Build Coastguard Worker         EndColumns();
5518*61046927SAndroid Build Coastguard Worker     PopClipRect();   // Inner window clip rectangle
5519*61046927SAndroid Build Coastguard Worker 
5520*61046927SAndroid Build Coastguard Worker     // Stop logging
5521*61046927SAndroid Build Coastguard Worker     if (!(window->Flags & ImGuiWindowFlags_ChildWindow))    // FIXME: add more options for scope of logging
5522*61046927SAndroid Build Coastguard Worker         LogFinish();
5523*61046927SAndroid Build Coastguard Worker 
5524*61046927SAndroid Build Coastguard Worker     // Pop from window stack
5525*61046927SAndroid Build Coastguard Worker     g.CurrentWindowStack.pop_back();
5526*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Popup)
5527*61046927SAndroid Build Coastguard Worker         g.BeginPopupStack.pop_back();
5528*61046927SAndroid Build Coastguard Worker     CheckStacksSize(window, false);
5529*61046927SAndroid Build Coastguard Worker     SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
5530*61046927SAndroid Build Coastguard Worker }
5531*61046927SAndroid Build Coastguard Worker 
BringWindowToFocusFront(ImGuiWindow * window)5532*61046927SAndroid Build Coastguard Worker void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
5533*61046927SAndroid Build Coastguard Worker {
5534*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5535*61046927SAndroid Build Coastguard Worker     if (g.WindowsFocusOrder.back() == window)
5536*61046927SAndroid Build Coastguard Worker         return;
5537*61046927SAndroid Build Coastguard Worker     for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window
5538*61046927SAndroid Build Coastguard Worker         if (g.WindowsFocusOrder[i] == window)
5539*61046927SAndroid Build Coastguard Worker         {
5540*61046927SAndroid Build Coastguard Worker             memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*));
5541*61046927SAndroid Build Coastguard Worker             g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window;
5542*61046927SAndroid Build Coastguard Worker             break;
5543*61046927SAndroid Build Coastguard Worker         }
5544*61046927SAndroid Build Coastguard Worker }
5545*61046927SAndroid Build Coastguard Worker 
BringWindowToDisplayFront(ImGuiWindow * window)5546*61046927SAndroid Build Coastguard Worker void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
5547*61046927SAndroid Build Coastguard Worker {
5548*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5549*61046927SAndroid Build Coastguard Worker     ImGuiWindow* current_front_window = g.Windows.back();
5550*61046927SAndroid Build Coastguard Worker     if (current_front_window == window || current_front_window->RootWindow == window)
5551*61046927SAndroid Build Coastguard Worker         return;
5552*61046927SAndroid Build Coastguard Worker     for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window
5553*61046927SAndroid Build Coastguard Worker         if (g.Windows[i] == window)
5554*61046927SAndroid Build Coastguard Worker         {
5555*61046927SAndroid Build Coastguard Worker             memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
5556*61046927SAndroid Build Coastguard Worker             g.Windows[g.Windows.Size - 1] = window;
5557*61046927SAndroid Build Coastguard Worker             break;
5558*61046927SAndroid Build Coastguard Worker         }
5559*61046927SAndroid Build Coastguard Worker }
5560*61046927SAndroid Build Coastguard Worker 
BringWindowToDisplayBack(ImGuiWindow * window)5561*61046927SAndroid Build Coastguard Worker void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
5562*61046927SAndroid Build Coastguard Worker {
5563*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5564*61046927SAndroid Build Coastguard Worker     if (g.Windows[0] == window)
5565*61046927SAndroid Build Coastguard Worker         return;
5566*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < g.Windows.Size; i++)
5567*61046927SAndroid Build Coastguard Worker         if (g.Windows[i] == window)
5568*61046927SAndroid Build Coastguard Worker         {
5569*61046927SAndroid Build Coastguard Worker             memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
5570*61046927SAndroid Build Coastguard Worker             g.Windows[0] = window;
5571*61046927SAndroid Build Coastguard Worker             break;
5572*61046927SAndroid Build Coastguard Worker         }
5573*61046927SAndroid Build Coastguard Worker }
5574*61046927SAndroid Build Coastguard Worker 
5575*61046927SAndroid Build Coastguard Worker // Moving window to front of display and set focus (which happens to be back of our sorted list)
FocusWindow(ImGuiWindow * window)5576*61046927SAndroid Build Coastguard Worker void ImGui::FocusWindow(ImGuiWindow* window)
5577*61046927SAndroid Build Coastguard Worker {
5578*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5579*61046927SAndroid Build Coastguard Worker 
5580*61046927SAndroid Build Coastguard Worker     if (g.NavWindow != window)
5581*61046927SAndroid Build Coastguard Worker     {
5582*61046927SAndroid Build Coastguard Worker         g.NavWindow = window;
5583*61046927SAndroid Build Coastguard Worker         if (window && g.NavDisableMouseHover)
5584*61046927SAndroid Build Coastguard Worker             g.NavMousePosDirty = true;
5585*61046927SAndroid Build Coastguard Worker         g.NavInitRequest = false;
5586*61046927SAndroid Build Coastguard Worker         g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
5587*61046927SAndroid Build Coastguard Worker         g.NavIdIsAlive = false;
5588*61046927SAndroid Build Coastguard Worker         g.NavLayer = ImGuiNavLayer_Main;
5589*61046927SAndroid Build Coastguard Worker         //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
5590*61046927SAndroid Build Coastguard Worker     }
5591*61046927SAndroid Build Coastguard Worker 
5592*61046927SAndroid Build Coastguard Worker     // Passing NULL allow to disable keyboard focus
5593*61046927SAndroid Build Coastguard Worker     if (!window)
5594*61046927SAndroid Build Coastguard Worker         return;
5595*61046927SAndroid Build Coastguard Worker 
5596*61046927SAndroid Build Coastguard Worker     // Move the root window to the top of the pile
5597*61046927SAndroid Build Coastguard Worker     if (window->RootWindow)
5598*61046927SAndroid Build Coastguard Worker         window = window->RootWindow;
5599*61046927SAndroid Build Coastguard Worker 
5600*61046927SAndroid Build Coastguard Worker     // Steal focus on active widgets
5601*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
5602*61046927SAndroid Build Coastguard Worker         if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
5603*61046927SAndroid Build Coastguard Worker             ClearActiveID();
5604*61046927SAndroid Build Coastguard Worker 
5605*61046927SAndroid Build Coastguard Worker     // Bring to front
5606*61046927SAndroid Build Coastguard Worker     BringWindowToFocusFront(window);
5607*61046927SAndroid Build Coastguard Worker     if (!(window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus))
5608*61046927SAndroid Build Coastguard Worker         BringWindowToDisplayFront(window);
5609*61046927SAndroid Build Coastguard Worker }
5610*61046927SAndroid Build Coastguard Worker 
FocusPreviousWindowIgnoringOne(ImGuiWindow * ignore_window)5611*61046927SAndroid Build Coastguard Worker void ImGui::FocusPreviousWindowIgnoringOne(ImGuiWindow* ignore_window)
5612*61046927SAndroid Build Coastguard Worker {
5613*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5614*61046927SAndroid Build Coastguard Worker     for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--)
5615*61046927SAndroid Build Coastguard Worker     {
5616*61046927SAndroid Build Coastguard Worker         // 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.
5617*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.WindowsFocusOrder[i];
5618*61046927SAndroid Build Coastguard Worker         if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow))
5619*61046927SAndroid Build Coastguard Worker             if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
5620*61046927SAndroid Build Coastguard Worker             {
5621*61046927SAndroid Build Coastguard Worker                 ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
5622*61046927SAndroid Build Coastguard Worker                 FocusWindow(focus_window);
5623*61046927SAndroid Build Coastguard Worker                 return;
5624*61046927SAndroid Build Coastguard Worker             }
5625*61046927SAndroid Build Coastguard Worker     }
5626*61046927SAndroid Build Coastguard Worker }
5627*61046927SAndroid Build Coastguard Worker 
PushItemWidth(float item_width)5628*61046927SAndroid Build Coastguard Worker void ImGui::PushItemWidth(float item_width)
5629*61046927SAndroid Build Coastguard Worker {
5630*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5631*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
5632*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
5633*61046927SAndroid Build Coastguard Worker }
5634*61046927SAndroid Build Coastguard Worker 
PushMultiItemsWidths(int components,float w_full)5635*61046927SAndroid Build Coastguard Worker void ImGui::PushMultiItemsWidths(int components, float w_full)
5636*61046927SAndroid Build Coastguard Worker {
5637*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5638*61046927SAndroid Build Coastguard Worker     const ImGuiStyle& style = GImGui->Style;
5639*61046927SAndroid Build Coastguard Worker     if (w_full <= 0.0f)
5640*61046927SAndroid Build Coastguard Worker         w_full = CalcItemWidth();
5641*61046927SAndroid Build Coastguard Worker     const float w_item_one  = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
5642*61046927SAndroid Build Coastguard Worker     const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
5643*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidthStack.push_back(w_item_last);
5644*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < components-1; i++)
5645*61046927SAndroid Build Coastguard Worker         window->DC.ItemWidthStack.push_back(w_item_one);
5646*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidth = window->DC.ItemWidthStack.back();
5647*61046927SAndroid Build Coastguard Worker }
5648*61046927SAndroid Build Coastguard Worker 
PopItemWidth()5649*61046927SAndroid Build Coastguard Worker void ImGui::PopItemWidth()
5650*61046927SAndroid Build Coastguard Worker {
5651*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5652*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidthStack.pop_back();
5653*61046927SAndroid Build Coastguard Worker     window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
5654*61046927SAndroid Build Coastguard Worker }
5655*61046927SAndroid Build Coastguard Worker 
CalcItemWidth()5656*61046927SAndroid Build Coastguard Worker float ImGui::CalcItemWidth()
5657*61046927SAndroid Build Coastguard Worker {
5658*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
5659*61046927SAndroid Build Coastguard Worker     float w = window->DC.ItemWidth;
5660*61046927SAndroid Build Coastguard Worker     if (w < 0.0f)
5661*61046927SAndroid Build Coastguard Worker     {
5662*61046927SAndroid Build Coastguard Worker         // 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.
5663*61046927SAndroid Build Coastguard Worker         float width_to_right_edge = GetContentRegionAvail().x;
5664*61046927SAndroid Build Coastguard Worker         w = ImMax(1.0f, width_to_right_edge + w);
5665*61046927SAndroid Build Coastguard Worker     }
5666*61046927SAndroid Build Coastguard Worker     w = (float)(int)w;
5667*61046927SAndroid Build Coastguard Worker     return w;
5668*61046927SAndroid Build Coastguard Worker }
5669*61046927SAndroid Build Coastguard Worker 
SetCurrentFont(ImFont * font)5670*61046927SAndroid Build Coastguard Worker void ImGui::SetCurrentFont(ImFont* font)
5671*61046927SAndroid Build Coastguard Worker {
5672*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5673*61046927SAndroid Build Coastguard Worker     IM_ASSERT(font && font->IsLoaded());    // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
5674*61046927SAndroid Build Coastguard Worker     IM_ASSERT(font->Scale > 0.0f);
5675*61046927SAndroid Build Coastguard Worker     g.Font = font;
5676*61046927SAndroid Build Coastguard Worker     g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale);
5677*61046927SAndroid Build Coastguard Worker     g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
5678*61046927SAndroid Build Coastguard Worker 
5679*61046927SAndroid Build Coastguard Worker     ImFontAtlas* atlas = g.Font->ContainerAtlas;
5680*61046927SAndroid Build Coastguard Worker     g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
5681*61046927SAndroid Build Coastguard Worker     g.DrawListSharedData.Font = g.Font;
5682*61046927SAndroid Build Coastguard Worker     g.DrawListSharedData.FontSize = g.FontSize;
5683*61046927SAndroid Build Coastguard Worker }
5684*61046927SAndroid Build Coastguard Worker 
PushFont(ImFont * font)5685*61046927SAndroid Build Coastguard Worker void ImGui::PushFont(ImFont* font)
5686*61046927SAndroid Build Coastguard Worker {
5687*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5688*61046927SAndroid Build Coastguard Worker     if (!font)
5689*61046927SAndroid Build Coastguard Worker         font = GetDefaultFont();
5690*61046927SAndroid Build Coastguard Worker     SetCurrentFont(font);
5691*61046927SAndroid Build Coastguard Worker     g.FontStack.push_back(font);
5692*61046927SAndroid Build Coastguard Worker     g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
5693*61046927SAndroid Build Coastguard Worker }
5694*61046927SAndroid Build Coastguard Worker 
PopFont()5695*61046927SAndroid Build Coastguard Worker void  ImGui::PopFont()
5696*61046927SAndroid Build Coastguard Worker {
5697*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5698*61046927SAndroid Build Coastguard Worker     g.CurrentWindow->DrawList->PopTextureID();
5699*61046927SAndroid Build Coastguard Worker     g.FontStack.pop_back();
5700*61046927SAndroid Build Coastguard Worker     SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());
5701*61046927SAndroid Build Coastguard Worker }
5702*61046927SAndroid Build Coastguard Worker 
PushItemFlag(ImGuiItemFlags option,bool enabled)5703*61046927SAndroid Build Coastguard Worker void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
5704*61046927SAndroid Build Coastguard Worker {
5705*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5706*61046927SAndroid Build Coastguard Worker     if (enabled)
5707*61046927SAndroid Build Coastguard Worker         window->DC.ItemFlags |= option;
5708*61046927SAndroid Build Coastguard Worker     else
5709*61046927SAndroid Build Coastguard Worker         window->DC.ItemFlags &= ~option;
5710*61046927SAndroid Build Coastguard Worker     window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5711*61046927SAndroid Build Coastguard Worker }
5712*61046927SAndroid Build Coastguard Worker 
PopItemFlag()5713*61046927SAndroid Build Coastguard Worker void ImGui::PopItemFlag()
5714*61046927SAndroid Build Coastguard Worker {
5715*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5716*61046927SAndroid Build Coastguard Worker     window->DC.ItemFlagsStack.pop_back();
5717*61046927SAndroid Build Coastguard Worker     window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
5718*61046927SAndroid Build Coastguard Worker }
5719*61046927SAndroid Build Coastguard Worker 
5720*61046927SAndroid Build Coastguard Worker // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
PushAllowKeyboardFocus(bool allow_keyboard_focus)5721*61046927SAndroid Build Coastguard Worker void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
5722*61046927SAndroid Build Coastguard Worker {
5723*61046927SAndroid Build Coastguard Worker     PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus);
5724*61046927SAndroid Build Coastguard Worker }
5725*61046927SAndroid Build Coastguard Worker 
PopAllowKeyboardFocus()5726*61046927SAndroid Build Coastguard Worker void ImGui::PopAllowKeyboardFocus()
5727*61046927SAndroid Build Coastguard Worker {
5728*61046927SAndroid Build Coastguard Worker     PopItemFlag();
5729*61046927SAndroid Build Coastguard Worker }
5730*61046927SAndroid Build Coastguard Worker 
PushButtonRepeat(bool repeat)5731*61046927SAndroid Build Coastguard Worker void ImGui::PushButtonRepeat(bool repeat)
5732*61046927SAndroid Build Coastguard Worker {
5733*61046927SAndroid Build Coastguard Worker     PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat);
5734*61046927SAndroid Build Coastguard Worker }
5735*61046927SAndroid Build Coastguard Worker 
PopButtonRepeat()5736*61046927SAndroid Build Coastguard Worker void ImGui::PopButtonRepeat()
5737*61046927SAndroid Build Coastguard Worker {
5738*61046927SAndroid Build Coastguard Worker     PopItemFlag();
5739*61046927SAndroid Build Coastguard Worker }
5740*61046927SAndroid Build Coastguard Worker 
PushTextWrapPos(float wrap_pos_x)5741*61046927SAndroid Build Coastguard Worker void ImGui::PushTextWrapPos(float wrap_pos_x)
5742*61046927SAndroid Build Coastguard Worker {
5743*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5744*61046927SAndroid Build Coastguard Worker     window->DC.TextWrapPos = wrap_pos_x;
5745*61046927SAndroid Build Coastguard Worker     window->DC.TextWrapPosStack.push_back(wrap_pos_x);
5746*61046927SAndroid Build Coastguard Worker }
5747*61046927SAndroid Build Coastguard Worker 
PopTextWrapPos()5748*61046927SAndroid Build Coastguard Worker void ImGui::PopTextWrapPos()
5749*61046927SAndroid Build Coastguard Worker {
5750*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
5751*61046927SAndroid Build Coastguard Worker     window->DC.TextWrapPosStack.pop_back();
5752*61046927SAndroid Build Coastguard Worker     window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back();
5753*61046927SAndroid Build Coastguard Worker }
5754*61046927SAndroid Build Coastguard Worker 
5755*61046927SAndroid Build Coastguard Worker // 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
PushStyleColor(ImGuiCol idx,ImU32 col)5756*61046927SAndroid Build Coastguard Worker void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
5757*61046927SAndroid Build Coastguard Worker {
5758*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5759*61046927SAndroid Build Coastguard Worker     ImGuiColorMod backup;
5760*61046927SAndroid Build Coastguard Worker     backup.Col = idx;
5761*61046927SAndroid Build Coastguard Worker     backup.BackupValue = g.Style.Colors[idx];
5762*61046927SAndroid Build Coastguard Worker     g.ColorModifiers.push_back(backup);
5763*61046927SAndroid Build Coastguard Worker     g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
5764*61046927SAndroid Build Coastguard Worker }
5765*61046927SAndroid Build Coastguard Worker 
PushStyleColor(ImGuiCol idx,const ImVec4 & col)5766*61046927SAndroid Build Coastguard Worker void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
5767*61046927SAndroid Build Coastguard Worker {
5768*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5769*61046927SAndroid Build Coastguard Worker     ImGuiColorMod backup;
5770*61046927SAndroid Build Coastguard Worker     backup.Col = idx;
5771*61046927SAndroid Build Coastguard Worker     backup.BackupValue = g.Style.Colors[idx];
5772*61046927SAndroid Build Coastguard Worker     g.ColorModifiers.push_back(backup);
5773*61046927SAndroid Build Coastguard Worker     g.Style.Colors[idx] = col;
5774*61046927SAndroid Build Coastguard Worker }
5775*61046927SAndroid Build Coastguard Worker 
PopStyleColor(int count)5776*61046927SAndroid Build Coastguard Worker void ImGui::PopStyleColor(int count)
5777*61046927SAndroid Build Coastguard Worker {
5778*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5779*61046927SAndroid Build Coastguard Worker     while (count > 0)
5780*61046927SAndroid Build Coastguard Worker     {
5781*61046927SAndroid Build Coastguard Worker         ImGuiColorMod& backup = g.ColorModifiers.back();
5782*61046927SAndroid Build Coastguard Worker         g.Style.Colors[backup.Col] = backup.BackupValue;
5783*61046927SAndroid Build Coastguard Worker         g.ColorModifiers.pop_back();
5784*61046927SAndroid Build Coastguard Worker         count--;
5785*61046927SAndroid Build Coastguard Worker     }
5786*61046927SAndroid Build Coastguard Worker }
5787*61046927SAndroid Build Coastguard Worker 
5788*61046927SAndroid Build Coastguard Worker struct ImGuiStyleVarInfo
5789*61046927SAndroid Build Coastguard Worker {
5790*61046927SAndroid Build Coastguard Worker     ImGuiDataType   Type;
5791*61046927SAndroid Build Coastguard Worker     ImU32           Count;
5792*61046927SAndroid Build Coastguard Worker     ImU32           Offset;
GetVarPtrImGuiStyleVarInfo5793*61046927SAndroid Build Coastguard Worker     void*           GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
5794*61046927SAndroid Build Coastguard Worker };
5795*61046927SAndroid Build Coastguard Worker 
5796*61046927SAndroid Build Coastguard Worker static const ImGuiStyleVarInfo GStyleVarInfo[] =
5797*61046927SAndroid Build Coastguard Worker {
5798*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) },               // ImGuiStyleVar_Alpha
5799*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) },       // ImGuiStyleVar_WindowPadding
5800*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) },      // ImGuiStyleVar_WindowRounding
5801*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) },    // ImGuiStyleVar_WindowBorderSize
5802*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) },       // ImGuiStyleVar_WindowMinSize
5803*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) },    // ImGuiStyleVar_WindowTitleAlign
5804*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) },       // ImGuiStyleVar_ChildRounding
5805*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) },     // ImGuiStyleVar_ChildBorderSize
5806*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) },       // ImGuiStyleVar_PopupRounding
5807*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) },     // ImGuiStyleVar_PopupBorderSize
5808*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) },        // ImGuiStyleVar_FramePadding
5809*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) },       // ImGuiStyleVar_FrameRounding
5810*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) },     // ImGuiStyleVar_FrameBorderSize
5811*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) },         // ImGuiStyleVar_ItemSpacing
5812*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) },    // ImGuiStyleVar_ItemInnerSpacing
5813*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) },       // ImGuiStyleVar_IndentSpacing
5814*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) },       // ImGuiStyleVar_ScrollbarSize
5815*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) },   // ImGuiStyleVar_ScrollbarRounding
5816*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) },         // ImGuiStyleVar_GrabMinSize
5817*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) },        // ImGuiStyleVar_GrabRounding
5818*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) },         // ImGuiStyleVar_TabRounding
5819*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) },     // ImGuiStyleVar_ButtonTextAlign
5820*61046927SAndroid Build Coastguard Worker     { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
5821*61046927SAndroid Build Coastguard Worker };
5822*61046927SAndroid Build Coastguard Worker 
GetStyleVarInfo(ImGuiStyleVar idx)5823*61046927SAndroid Build Coastguard Worker static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
5824*61046927SAndroid Build Coastguard Worker {
5825*61046927SAndroid Build Coastguard Worker     IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
5826*61046927SAndroid Build Coastguard Worker     IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
5827*61046927SAndroid Build Coastguard Worker     return &GStyleVarInfo[idx];
5828*61046927SAndroid Build Coastguard Worker }
5829*61046927SAndroid Build Coastguard Worker 
PushStyleVar(ImGuiStyleVar idx,float val)5830*61046927SAndroid Build Coastguard Worker void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
5831*61046927SAndroid Build Coastguard Worker {
5832*61046927SAndroid Build Coastguard Worker     const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
5833*61046927SAndroid Build Coastguard Worker     if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
5834*61046927SAndroid Build Coastguard Worker     {
5835*61046927SAndroid Build Coastguard Worker         ImGuiContext& g = *GImGui;
5836*61046927SAndroid Build Coastguard Worker         float* pvar = (float*)var_info->GetVarPtr(&g.Style);
5837*61046927SAndroid Build Coastguard Worker         g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
5838*61046927SAndroid Build Coastguard Worker         *pvar = val;
5839*61046927SAndroid Build Coastguard Worker         return;
5840*61046927SAndroid Build Coastguard Worker     }
5841*61046927SAndroid Build Coastguard Worker     IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.
5842*61046927SAndroid Build Coastguard Worker }
5843*61046927SAndroid Build Coastguard Worker 
PushStyleVar(ImGuiStyleVar idx,const ImVec2 & val)5844*61046927SAndroid Build Coastguard Worker void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
5845*61046927SAndroid Build Coastguard Worker {
5846*61046927SAndroid Build Coastguard Worker     const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
5847*61046927SAndroid Build Coastguard Worker     if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
5848*61046927SAndroid Build Coastguard Worker     {
5849*61046927SAndroid Build Coastguard Worker         ImGuiContext& g = *GImGui;
5850*61046927SAndroid Build Coastguard Worker         ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
5851*61046927SAndroid Build Coastguard Worker         g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
5852*61046927SAndroid Build Coastguard Worker         *pvar = val;
5853*61046927SAndroid Build Coastguard Worker         return;
5854*61046927SAndroid Build Coastguard Worker     }
5855*61046927SAndroid Build Coastguard Worker     IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.
5856*61046927SAndroid Build Coastguard Worker }
5857*61046927SAndroid Build Coastguard Worker 
PopStyleVar(int count)5858*61046927SAndroid Build Coastguard Worker void ImGui::PopStyleVar(int count)
5859*61046927SAndroid Build Coastguard Worker {
5860*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5861*61046927SAndroid Build Coastguard Worker     while (count > 0)
5862*61046927SAndroid Build Coastguard Worker     {
5863*61046927SAndroid Build Coastguard Worker         // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
5864*61046927SAndroid Build Coastguard Worker         ImGuiStyleMod& backup = g.StyleModifiers.back();
5865*61046927SAndroid Build Coastguard Worker         const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
5866*61046927SAndroid Build Coastguard Worker         void* data = info->GetVarPtr(&g.Style);
5867*61046927SAndroid Build Coastguard Worker         if (info->Type == ImGuiDataType_Float && info->Count == 1)      { ((float*)data)[0] = backup.BackupFloat[0]; }
5868*61046927SAndroid Build Coastguard Worker         else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
5869*61046927SAndroid Build Coastguard Worker         g.StyleModifiers.pop_back();
5870*61046927SAndroid Build Coastguard Worker         count--;
5871*61046927SAndroid Build Coastguard Worker     }
5872*61046927SAndroid Build Coastguard Worker }
5873*61046927SAndroid Build Coastguard Worker 
GetStyleColorName(ImGuiCol idx)5874*61046927SAndroid Build Coastguard Worker const char* ImGui::GetStyleColorName(ImGuiCol idx)
5875*61046927SAndroid Build Coastguard Worker {
5876*61046927SAndroid Build Coastguard Worker     // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
5877*61046927SAndroid Build Coastguard Worker     switch (idx)
5878*61046927SAndroid Build Coastguard Worker     {
5879*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Text: return "Text";
5880*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TextDisabled: return "TextDisabled";
5881*61046927SAndroid Build Coastguard Worker     case ImGuiCol_WindowBg: return "WindowBg";
5882*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ChildBg: return "ChildBg";
5883*61046927SAndroid Build Coastguard Worker     case ImGuiCol_PopupBg: return "PopupBg";
5884*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Border: return "Border";
5885*61046927SAndroid Build Coastguard Worker     case ImGuiCol_BorderShadow: return "BorderShadow";
5886*61046927SAndroid Build Coastguard Worker     case ImGuiCol_FrameBg: return "FrameBg";
5887*61046927SAndroid Build Coastguard Worker     case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
5888*61046927SAndroid Build Coastguard Worker     case ImGuiCol_FrameBgActive: return "FrameBgActive";
5889*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TitleBg: return "TitleBg";
5890*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TitleBgActive: return "TitleBgActive";
5891*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
5892*61046927SAndroid Build Coastguard Worker     case ImGuiCol_MenuBarBg: return "MenuBarBg";
5893*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
5894*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
5895*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
5896*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
5897*61046927SAndroid Build Coastguard Worker     case ImGuiCol_CheckMark: return "CheckMark";
5898*61046927SAndroid Build Coastguard Worker     case ImGuiCol_SliderGrab: return "SliderGrab";
5899*61046927SAndroid Build Coastguard Worker     case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
5900*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Button: return "Button";
5901*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ButtonHovered: return "ButtonHovered";
5902*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ButtonActive: return "ButtonActive";
5903*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Header: return "Header";
5904*61046927SAndroid Build Coastguard Worker     case ImGuiCol_HeaderHovered: return "HeaderHovered";
5905*61046927SAndroid Build Coastguard Worker     case ImGuiCol_HeaderActive: return "HeaderActive";
5906*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Separator: return "Separator";
5907*61046927SAndroid Build Coastguard Worker     case ImGuiCol_SeparatorHovered: return "SeparatorHovered";
5908*61046927SAndroid Build Coastguard Worker     case ImGuiCol_SeparatorActive: return "SeparatorActive";
5909*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ResizeGrip: return "ResizeGrip";
5910*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
5911*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
5912*61046927SAndroid Build Coastguard Worker     case ImGuiCol_Tab: return "Tab";
5913*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TabHovered: return "TabHovered";
5914*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TabActive: return "TabActive";
5915*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TabUnfocused: return "TabUnfocused";
5916*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
5917*61046927SAndroid Build Coastguard Worker     case ImGuiCol_PlotLines: return "PlotLines";
5918*61046927SAndroid Build Coastguard Worker     case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
5919*61046927SAndroid Build Coastguard Worker     case ImGuiCol_PlotHistogram: return "PlotHistogram";
5920*61046927SAndroid Build Coastguard Worker     case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
5921*61046927SAndroid Build Coastguard Worker     case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
5922*61046927SAndroid Build Coastguard Worker     case ImGuiCol_DragDropTarget: return "DragDropTarget";
5923*61046927SAndroid Build Coastguard Worker     case ImGuiCol_NavHighlight: return "NavHighlight";
5924*61046927SAndroid Build Coastguard Worker     case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
5925*61046927SAndroid Build Coastguard Worker     case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
5926*61046927SAndroid Build Coastguard Worker     case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
5927*61046927SAndroid Build Coastguard Worker     }
5928*61046927SAndroid Build Coastguard Worker     IM_ASSERT(0);
5929*61046927SAndroid Build Coastguard Worker     return "Unknown";
5930*61046927SAndroid Build Coastguard Worker }
5931*61046927SAndroid Build Coastguard Worker 
IsWindowChildOf(ImGuiWindow * window,ImGuiWindow * potential_parent)5932*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
5933*61046927SAndroid Build Coastguard Worker {
5934*61046927SAndroid Build Coastguard Worker     if (window->RootWindow == potential_parent)
5935*61046927SAndroid Build Coastguard Worker         return true;
5936*61046927SAndroid Build Coastguard Worker     while (window != NULL)
5937*61046927SAndroid Build Coastguard Worker     {
5938*61046927SAndroid Build Coastguard Worker         if (window == potential_parent)
5939*61046927SAndroid Build Coastguard Worker             return true;
5940*61046927SAndroid Build Coastguard Worker         window = window->ParentWindow;
5941*61046927SAndroid Build Coastguard Worker     }
5942*61046927SAndroid Build Coastguard Worker     return false;
5943*61046927SAndroid Build Coastguard Worker }
5944*61046927SAndroid Build Coastguard Worker 
IsWindowHovered(ImGuiHoveredFlags flags)5945*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
5946*61046927SAndroid Build Coastguard Worker {
5947*61046927SAndroid Build Coastguard Worker     IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0);   // Flags not supported by this function
5948*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5949*61046927SAndroid Build Coastguard Worker 
5950*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiHoveredFlags_AnyWindow)
5951*61046927SAndroid Build Coastguard Worker     {
5952*61046927SAndroid Build Coastguard Worker         if (g.HoveredWindow == NULL)
5953*61046927SAndroid Build Coastguard Worker             return false;
5954*61046927SAndroid Build Coastguard Worker     }
5955*61046927SAndroid Build Coastguard Worker     else
5956*61046927SAndroid Build Coastguard Worker     {
5957*61046927SAndroid Build Coastguard Worker         switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows))
5958*61046927SAndroid Build Coastguard Worker         {
5959*61046927SAndroid Build Coastguard Worker         case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows:
5960*61046927SAndroid Build Coastguard Worker             if (g.HoveredRootWindow != g.CurrentWindow->RootWindow)
5961*61046927SAndroid Build Coastguard Worker                 return false;
5962*61046927SAndroid Build Coastguard Worker             break;
5963*61046927SAndroid Build Coastguard Worker         case ImGuiHoveredFlags_RootWindow:
5964*61046927SAndroid Build Coastguard Worker             if (g.HoveredWindow != g.CurrentWindow->RootWindow)
5965*61046927SAndroid Build Coastguard Worker                 return false;
5966*61046927SAndroid Build Coastguard Worker             break;
5967*61046927SAndroid Build Coastguard Worker         case ImGuiHoveredFlags_ChildWindows:
5968*61046927SAndroid Build Coastguard Worker             if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow))
5969*61046927SAndroid Build Coastguard Worker                 return false;
5970*61046927SAndroid Build Coastguard Worker             break;
5971*61046927SAndroid Build Coastguard Worker         default:
5972*61046927SAndroid Build Coastguard Worker             if (g.HoveredWindow != g.CurrentWindow)
5973*61046927SAndroid Build Coastguard Worker                 return false;
5974*61046927SAndroid Build Coastguard Worker             break;
5975*61046927SAndroid Build Coastguard Worker         }
5976*61046927SAndroid Build Coastguard Worker     }
5977*61046927SAndroid Build Coastguard Worker 
5978*61046927SAndroid Build Coastguard Worker     if (!IsWindowContentHoverable(g.HoveredRootWindow, flags))
5979*61046927SAndroid Build Coastguard Worker         return false;
5980*61046927SAndroid Build Coastguard Worker     if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
5981*61046927SAndroid Build Coastguard Worker         if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId)
5982*61046927SAndroid Build Coastguard Worker             return false;
5983*61046927SAndroid Build Coastguard Worker     return true;
5984*61046927SAndroid Build Coastguard Worker }
5985*61046927SAndroid Build Coastguard Worker 
IsWindowFocused(ImGuiFocusedFlags flags)5986*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
5987*61046927SAndroid Build Coastguard Worker {
5988*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
5989*61046927SAndroid Build Coastguard Worker 
5990*61046927SAndroid Build Coastguard Worker     if (flags & ImGuiFocusedFlags_AnyWindow)
5991*61046927SAndroid Build Coastguard Worker         return g.NavWindow != NULL;
5992*61046927SAndroid Build Coastguard Worker 
5993*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.CurrentWindow);     // Not inside a Begin()/End()
5994*61046927SAndroid Build Coastguard Worker     switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows))
5995*61046927SAndroid Build Coastguard Worker     {
5996*61046927SAndroid Build Coastguard Worker     case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows:
5997*61046927SAndroid Build Coastguard Worker         return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
5998*61046927SAndroid Build Coastguard Worker     case ImGuiFocusedFlags_RootWindow:
5999*61046927SAndroid Build Coastguard Worker         return g.NavWindow == g.CurrentWindow->RootWindow;
6000*61046927SAndroid Build Coastguard Worker     case ImGuiFocusedFlags_ChildWindows:
6001*61046927SAndroid Build Coastguard Worker         return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow);
6002*61046927SAndroid Build Coastguard Worker     default:
6003*61046927SAndroid Build Coastguard Worker         return g.NavWindow == g.CurrentWindow;
6004*61046927SAndroid Build Coastguard Worker     }
6005*61046927SAndroid Build Coastguard Worker }
6006*61046927SAndroid Build Coastguard Worker 
6007*61046927SAndroid Build Coastguard Worker // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
6008*61046927SAndroid Build Coastguard Worker // Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly.
6009*61046927SAndroid Build Coastguard Worker // If you want a window to never be focused, you may use the e.g. NoInputs flag.
IsWindowNavFocusable(ImGuiWindow * window)6010*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
6011*61046927SAndroid Build Coastguard Worker {
6012*61046927SAndroid Build Coastguard Worker     return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
6013*61046927SAndroid Build Coastguard Worker }
6014*61046927SAndroid Build Coastguard Worker 
GetWindowWidth()6015*61046927SAndroid Build Coastguard Worker float ImGui::GetWindowWidth()
6016*61046927SAndroid Build Coastguard Worker {
6017*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6018*61046927SAndroid Build Coastguard Worker     return window->Size.x;
6019*61046927SAndroid Build Coastguard Worker }
6020*61046927SAndroid Build Coastguard Worker 
GetWindowHeight()6021*61046927SAndroid Build Coastguard Worker float ImGui::GetWindowHeight()
6022*61046927SAndroid Build Coastguard Worker {
6023*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6024*61046927SAndroid Build Coastguard Worker     return window->Size.y;
6025*61046927SAndroid Build Coastguard Worker }
6026*61046927SAndroid Build Coastguard Worker 
GetWindowPos()6027*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetWindowPos()
6028*61046927SAndroid Build Coastguard Worker {
6029*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6030*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
6031*61046927SAndroid Build Coastguard Worker     return window->Pos;
6032*61046927SAndroid Build Coastguard Worker }
6033*61046927SAndroid Build Coastguard Worker 
SetWindowScrollX(ImGuiWindow * window,float new_scroll_x)6034*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
6035*61046927SAndroid Build Coastguard Worker {
6036*61046927SAndroid Build Coastguard Worker     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.
6037*61046927SAndroid Build Coastguard Worker     window->Scroll.x = new_scroll_x;
6038*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.x -= window->Scroll.x;
6039*61046927SAndroid Build Coastguard Worker }
6040*61046927SAndroid Build Coastguard Worker 
SetWindowScrollY(ImGuiWindow * window,float new_scroll_y)6041*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
6042*61046927SAndroid Build Coastguard Worker {
6043*61046927SAndroid Build Coastguard Worker     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.
6044*61046927SAndroid Build Coastguard Worker     window->Scroll.y = new_scroll_y;
6045*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.y -= window->Scroll.y;
6046*61046927SAndroid Build Coastguard Worker }
6047*61046927SAndroid Build Coastguard Worker 
SetWindowPos(ImGuiWindow * window,const ImVec2 & pos,ImGuiCond cond)6048*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
6049*61046927SAndroid Build Coastguard Worker {
6050*61046927SAndroid Build Coastguard Worker     // Test condition (NB: bit 0 is always true) and clear flags for next time
6051*61046927SAndroid Build Coastguard Worker     if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
6052*61046927SAndroid Build Coastguard Worker         return;
6053*61046927SAndroid Build Coastguard Worker 
6054*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6055*61046927SAndroid Build Coastguard Worker     window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6056*61046927SAndroid Build Coastguard Worker     window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
6057*61046927SAndroid Build Coastguard Worker 
6058*61046927SAndroid Build Coastguard Worker     // Set
6059*61046927SAndroid Build Coastguard Worker     const ImVec2 old_pos = window->Pos;
6060*61046927SAndroid Build Coastguard Worker     window->Pos = ImFloor(pos);
6061*61046927SAndroid Build Coastguard Worker     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
6062*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
6063*61046927SAndroid Build Coastguard Worker }
6064*61046927SAndroid Build Coastguard Worker 
SetWindowPos(const ImVec2 & pos,ImGuiCond cond)6065*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
6066*61046927SAndroid Build Coastguard Worker {
6067*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6068*61046927SAndroid Build Coastguard Worker     SetWindowPos(window, pos, cond);
6069*61046927SAndroid Build Coastguard Worker }
6070*61046927SAndroid Build Coastguard Worker 
SetWindowPos(const char * name,const ImVec2 & pos,ImGuiCond cond)6071*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond)
6072*61046927SAndroid Build Coastguard Worker {
6073*61046927SAndroid Build Coastguard Worker     if (ImGuiWindow* window = FindWindowByName(name))
6074*61046927SAndroid Build Coastguard Worker         SetWindowPos(window, pos, cond);
6075*61046927SAndroid Build Coastguard Worker }
6076*61046927SAndroid Build Coastguard Worker 
GetWindowSize()6077*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetWindowSize()
6078*61046927SAndroid Build Coastguard Worker {
6079*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6080*61046927SAndroid Build Coastguard Worker     return window->Size;
6081*61046927SAndroid Build Coastguard Worker }
6082*61046927SAndroid Build Coastguard Worker 
SetWindowSize(ImGuiWindow * window,const ImVec2 & size,ImGuiCond cond)6083*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)
6084*61046927SAndroid Build Coastguard Worker {
6085*61046927SAndroid Build Coastguard Worker     // Test condition (NB: bit 0 is always true) and clear flags for next time
6086*61046927SAndroid Build Coastguard Worker     if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
6087*61046927SAndroid Build Coastguard Worker         return;
6088*61046927SAndroid Build Coastguard Worker 
6089*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6090*61046927SAndroid Build Coastguard Worker     window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6091*61046927SAndroid Build Coastguard Worker 
6092*61046927SAndroid Build Coastguard Worker     // Set
6093*61046927SAndroid Build Coastguard Worker     if (size.x > 0.0f)
6094*61046927SAndroid Build Coastguard Worker     {
6095*61046927SAndroid Build Coastguard Worker         window->AutoFitFramesX = 0;
6096*61046927SAndroid Build Coastguard Worker         window->SizeFull.x = ImFloor(size.x);
6097*61046927SAndroid Build Coastguard Worker     }
6098*61046927SAndroid Build Coastguard Worker     else
6099*61046927SAndroid Build Coastguard Worker     {
6100*61046927SAndroid Build Coastguard Worker         window->AutoFitFramesX = 2;
6101*61046927SAndroid Build Coastguard Worker         window->AutoFitOnlyGrows = false;
6102*61046927SAndroid Build Coastguard Worker     }
6103*61046927SAndroid Build Coastguard Worker     if (size.y > 0.0f)
6104*61046927SAndroid Build Coastguard Worker     {
6105*61046927SAndroid Build Coastguard Worker         window->AutoFitFramesY = 0;
6106*61046927SAndroid Build Coastguard Worker         window->SizeFull.y = ImFloor(size.y);
6107*61046927SAndroid Build Coastguard Worker     }
6108*61046927SAndroid Build Coastguard Worker     else
6109*61046927SAndroid Build Coastguard Worker     {
6110*61046927SAndroid Build Coastguard Worker         window->AutoFitFramesY = 2;
6111*61046927SAndroid Build Coastguard Worker         window->AutoFitOnlyGrows = false;
6112*61046927SAndroid Build Coastguard Worker     }
6113*61046927SAndroid Build Coastguard Worker }
6114*61046927SAndroid Build Coastguard Worker 
SetWindowSize(const ImVec2 & size,ImGuiCond cond)6115*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond)
6116*61046927SAndroid Build Coastguard Worker {
6117*61046927SAndroid Build Coastguard Worker     SetWindowSize(GImGui->CurrentWindow, size, cond);
6118*61046927SAndroid Build Coastguard Worker }
6119*61046927SAndroid Build Coastguard Worker 
SetWindowSize(const char * name,const ImVec2 & size,ImGuiCond cond)6120*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond)
6121*61046927SAndroid Build Coastguard Worker {
6122*61046927SAndroid Build Coastguard Worker     if (ImGuiWindow* window = FindWindowByName(name))
6123*61046927SAndroid Build Coastguard Worker         SetWindowSize(window, size, cond);
6124*61046927SAndroid Build Coastguard Worker }
6125*61046927SAndroid Build Coastguard Worker 
SetWindowCollapsed(ImGuiWindow * window,bool collapsed,ImGuiCond cond)6126*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)
6127*61046927SAndroid Build Coastguard Worker {
6128*61046927SAndroid Build Coastguard Worker     // Test condition (NB: bit 0 is always true) and clear flags for next time
6129*61046927SAndroid Build Coastguard Worker     if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
6130*61046927SAndroid Build Coastguard Worker         return;
6131*61046927SAndroid Build Coastguard Worker     window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6132*61046927SAndroid Build Coastguard Worker 
6133*61046927SAndroid Build Coastguard Worker     // Set
6134*61046927SAndroid Build Coastguard Worker     window->Collapsed = collapsed;
6135*61046927SAndroid Build Coastguard Worker }
6136*61046927SAndroid Build Coastguard Worker 
SetWindowCollapsed(bool collapsed,ImGuiCond cond)6137*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
6138*61046927SAndroid Build Coastguard Worker {
6139*61046927SAndroid Build Coastguard Worker     SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
6140*61046927SAndroid Build Coastguard Worker }
6141*61046927SAndroid Build Coastguard Worker 
IsWindowCollapsed()6142*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowCollapsed()
6143*61046927SAndroid Build Coastguard Worker {
6144*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6145*61046927SAndroid Build Coastguard Worker     return window->Collapsed;
6146*61046927SAndroid Build Coastguard Worker }
6147*61046927SAndroid Build Coastguard Worker 
IsWindowAppearing()6148*61046927SAndroid Build Coastguard Worker bool ImGui::IsWindowAppearing()
6149*61046927SAndroid Build Coastguard Worker {
6150*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6151*61046927SAndroid Build Coastguard Worker     return window->Appearing;
6152*61046927SAndroid Build Coastguard Worker }
6153*61046927SAndroid Build Coastguard Worker 
SetWindowCollapsed(const char * name,bool collapsed,ImGuiCond cond)6154*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
6155*61046927SAndroid Build Coastguard Worker {
6156*61046927SAndroid Build Coastguard Worker     if (ImGuiWindow* window = FindWindowByName(name))
6157*61046927SAndroid Build Coastguard Worker         SetWindowCollapsed(window, collapsed, cond);
6158*61046927SAndroid Build Coastguard Worker }
6159*61046927SAndroid Build Coastguard Worker 
SetWindowFocus()6160*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowFocus()
6161*61046927SAndroid Build Coastguard Worker {
6162*61046927SAndroid Build Coastguard Worker     FocusWindow(GImGui->CurrentWindow);
6163*61046927SAndroid Build Coastguard Worker }
6164*61046927SAndroid Build Coastguard Worker 
SetWindowFocus(const char * name)6165*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowFocus(const char* name)
6166*61046927SAndroid Build Coastguard Worker {
6167*61046927SAndroid Build Coastguard Worker     if (name)
6168*61046927SAndroid Build Coastguard Worker     {
6169*61046927SAndroid Build Coastguard Worker         if (ImGuiWindow* window = FindWindowByName(name))
6170*61046927SAndroid Build Coastguard Worker             FocusWindow(window);
6171*61046927SAndroid Build Coastguard Worker     }
6172*61046927SAndroid Build Coastguard Worker     else
6173*61046927SAndroid Build Coastguard Worker     {
6174*61046927SAndroid Build Coastguard Worker         FocusWindow(NULL);
6175*61046927SAndroid Build Coastguard Worker     }
6176*61046927SAndroid Build Coastguard Worker }
6177*61046927SAndroid Build Coastguard Worker 
SetNextWindowPos(const ImVec2 & pos,ImGuiCond cond,const ImVec2 & pivot)6178*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
6179*61046927SAndroid Build Coastguard Worker {
6180*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6181*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6182*61046927SAndroid Build Coastguard Worker     g.NextWindowData.PosVal = pos;
6183*61046927SAndroid Build Coastguard Worker     g.NextWindowData.PosPivotVal = pivot;
6184*61046927SAndroid Build Coastguard Worker     g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
6185*61046927SAndroid Build Coastguard Worker }
6186*61046927SAndroid Build Coastguard Worker 
SetNextWindowSize(const ImVec2 & size,ImGuiCond cond)6187*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
6188*61046927SAndroid Build Coastguard Worker {
6189*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6190*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6191*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeVal = size;
6192*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
6193*61046927SAndroid Build Coastguard Worker }
6194*61046927SAndroid Build Coastguard Worker 
SetNextWindowSizeConstraints(const ImVec2 & size_min,const ImVec2 & size_max,ImGuiSizeCallback custom_callback,void * custom_callback_user_data)6195*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
6196*61046927SAndroid Build Coastguard Worker {
6197*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6198*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeConstraintCond = ImGuiCond_Always;
6199*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
6200*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeCallback = custom_callback;
6201*61046927SAndroid Build Coastguard Worker     g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
6202*61046927SAndroid Build Coastguard Worker }
6203*61046927SAndroid Build Coastguard Worker 
SetNextWindowContentSize(const ImVec2 & size)6204*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowContentSize(const ImVec2& size)
6205*61046927SAndroid Build Coastguard Worker {
6206*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6207*61046927SAndroid Build Coastguard Worker     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.
6208*61046927SAndroid Build Coastguard Worker     g.NextWindowData.ContentSizeCond = ImGuiCond_Always;
6209*61046927SAndroid Build Coastguard Worker }
6210*61046927SAndroid Build Coastguard Worker 
SetNextWindowCollapsed(bool collapsed,ImGuiCond cond)6211*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
6212*61046927SAndroid Build Coastguard Worker {
6213*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6214*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
6215*61046927SAndroid Build Coastguard Worker     g.NextWindowData.CollapsedVal = collapsed;
6216*61046927SAndroid Build Coastguard Worker     g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
6217*61046927SAndroid Build Coastguard Worker }
6218*61046927SAndroid Build Coastguard Worker 
SetNextWindowFocus()6219*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowFocus()
6220*61046927SAndroid Build Coastguard Worker {
6221*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6222*61046927SAndroid Build Coastguard Worker     g.NextWindowData.FocusCond = ImGuiCond_Always;   // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
6223*61046927SAndroid Build Coastguard Worker }
6224*61046927SAndroid Build Coastguard Worker 
SetNextWindowBgAlpha(float alpha)6225*61046927SAndroid Build Coastguard Worker void ImGui::SetNextWindowBgAlpha(float alpha)
6226*61046927SAndroid Build Coastguard Worker {
6227*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6228*61046927SAndroid Build Coastguard Worker     g.NextWindowData.BgAlphaVal = alpha;
6229*61046927SAndroid Build Coastguard Worker     g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
6230*61046927SAndroid Build Coastguard Worker }
6231*61046927SAndroid Build Coastguard Worker 
6232*61046927SAndroid Build Coastguard Worker // FIXME: This is in window space (not screen space!)
GetContentRegionMax()6233*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetContentRegionMax()
6234*61046927SAndroid Build Coastguard Worker {
6235*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6236*61046927SAndroid Build Coastguard Worker     ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
6237*61046927SAndroid Build Coastguard Worker     if (window->DC.ColumnsSet)
6238*61046927SAndroid Build Coastguard Worker         mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x;
6239*61046927SAndroid Build Coastguard Worker     return mx;
6240*61046927SAndroid Build Coastguard Worker }
6241*61046927SAndroid Build Coastguard Worker 
GetContentRegionAvail()6242*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetContentRegionAvail()
6243*61046927SAndroid Build Coastguard Worker {
6244*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6245*61046927SAndroid Build Coastguard Worker     return GetContentRegionMax() - (window->DC.CursorPos - window->Pos);
6246*61046927SAndroid Build Coastguard Worker }
6247*61046927SAndroid Build Coastguard Worker 
GetContentRegionAvailWidth()6248*61046927SAndroid Build Coastguard Worker float ImGui::GetContentRegionAvailWidth()
6249*61046927SAndroid Build Coastguard Worker {
6250*61046927SAndroid Build Coastguard Worker     return GetContentRegionAvail().x;
6251*61046927SAndroid Build Coastguard Worker }
6252*61046927SAndroid Build Coastguard Worker 
6253*61046927SAndroid Build Coastguard Worker // In window space (not screen space!)
GetWindowContentRegionMin()6254*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetWindowContentRegionMin()
6255*61046927SAndroid Build Coastguard Worker {
6256*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6257*61046927SAndroid Build Coastguard Worker     return window->ContentsRegionRect.Min - window->Pos;
6258*61046927SAndroid Build Coastguard Worker }
6259*61046927SAndroid Build Coastguard Worker 
GetWindowContentRegionMax()6260*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetWindowContentRegionMax()
6261*61046927SAndroid Build Coastguard Worker {
6262*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6263*61046927SAndroid Build Coastguard Worker     return window->ContentsRegionRect.Max - window->Pos;
6264*61046927SAndroid Build Coastguard Worker }
6265*61046927SAndroid Build Coastguard Worker 
GetWindowContentRegionWidth()6266*61046927SAndroid Build Coastguard Worker float ImGui::GetWindowContentRegionWidth()
6267*61046927SAndroid Build Coastguard Worker {
6268*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6269*61046927SAndroid Build Coastguard Worker     return window->ContentsRegionRect.GetWidth();
6270*61046927SAndroid Build Coastguard Worker }
6271*61046927SAndroid Build Coastguard Worker 
GetTextLineHeight()6272*61046927SAndroid Build Coastguard Worker float ImGui::GetTextLineHeight()
6273*61046927SAndroid Build Coastguard Worker {
6274*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6275*61046927SAndroid Build Coastguard Worker     return g.FontSize;
6276*61046927SAndroid Build Coastguard Worker }
6277*61046927SAndroid Build Coastguard Worker 
GetTextLineHeightWithSpacing()6278*61046927SAndroid Build Coastguard Worker float ImGui::GetTextLineHeightWithSpacing()
6279*61046927SAndroid Build Coastguard Worker {
6280*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6281*61046927SAndroid Build Coastguard Worker     return g.FontSize + g.Style.ItemSpacing.y;
6282*61046927SAndroid Build Coastguard Worker }
6283*61046927SAndroid Build Coastguard Worker 
GetFrameHeight()6284*61046927SAndroid Build Coastguard Worker float ImGui::GetFrameHeight()
6285*61046927SAndroid Build Coastguard Worker {
6286*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6287*61046927SAndroid Build Coastguard Worker     return g.FontSize + g.Style.FramePadding.y * 2.0f;
6288*61046927SAndroid Build Coastguard Worker }
6289*61046927SAndroid Build Coastguard Worker 
GetFrameHeightWithSpacing()6290*61046927SAndroid Build Coastguard Worker float ImGui::GetFrameHeightWithSpacing()
6291*61046927SAndroid Build Coastguard Worker {
6292*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6293*61046927SAndroid Build Coastguard Worker     return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
6294*61046927SAndroid Build Coastguard Worker }
6295*61046927SAndroid Build Coastguard Worker 
GetWindowDrawList()6296*61046927SAndroid Build Coastguard Worker ImDrawList* ImGui::GetWindowDrawList()
6297*61046927SAndroid Build Coastguard Worker {
6298*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6299*61046927SAndroid Build Coastguard Worker     return window->DrawList;
6300*61046927SAndroid Build Coastguard Worker }
6301*61046927SAndroid Build Coastguard Worker 
GetFont()6302*61046927SAndroid Build Coastguard Worker ImFont* ImGui::GetFont()
6303*61046927SAndroid Build Coastguard Worker {
6304*61046927SAndroid Build Coastguard Worker     return GImGui->Font;
6305*61046927SAndroid Build Coastguard Worker }
6306*61046927SAndroid Build Coastguard Worker 
GetFontSize()6307*61046927SAndroid Build Coastguard Worker float ImGui::GetFontSize()
6308*61046927SAndroid Build Coastguard Worker {
6309*61046927SAndroid Build Coastguard Worker     return GImGui->FontSize;
6310*61046927SAndroid Build Coastguard Worker }
6311*61046927SAndroid Build Coastguard Worker 
GetFontTexUvWhitePixel()6312*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetFontTexUvWhitePixel()
6313*61046927SAndroid Build Coastguard Worker {
6314*61046927SAndroid Build Coastguard Worker     return GImGui->DrawListSharedData.TexUvWhitePixel;
6315*61046927SAndroid Build Coastguard Worker }
6316*61046927SAndroid Build Coastguard Worker 
SetWindowFontScale(float scale)6317*61046927SAndroid Build Coastguard Worker void ImGui::SetWindowFontScale(float scale)
6318*61046927SAndroid Build Coastguard Worker {
6319*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6320*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6321*61046927SAndroid Build Coastguard Worker     window->FontWindowScale = scale;
6322*61046927SAndroid Build Coastguard Worker     g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
6323*61046927SAndroid Build Coastguard Worker }
6324*61046927SAndroid Build Coastguard Worker 
6325*61046927SAndroid Build Coastguard Worker // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
6326*61046927SAndroid Build Coastguard Worker // 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'.
GetCursorPos()6327*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetCursorPos()
6328*61046927SAndroid Build Coastguard Worker {
6329*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6330*61046927SAndroid Build Coastguard Worker     return window->DC.CursorPos - window->Pos + window->Scroll;
6331*61046927SAndroid Build Coastguard Worker }
6332*61046927SAndroid Build Coastguard Worker 
GetCursorPosX()6333*61046927SAndroid Build Coastguard Worker float ImGui::GetCursorPosX()
6334*61046927SAndroid Build Coastguard Worker {
6335*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6336*61046927SAndroid Build Coastguard Worker     return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
6337*61046927SAndroid Build Coastguard Worker }
6338*61046927SAndroid Build Coastguard Worker 
GetCursorPosY()6339*61046927SAndroid Build Coastguard Worker float ImGui::GetCursorPosY()
6340*61046927SAndroid Build Coastguard Worker {
6341*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6342*61046927SAndroid Build Coastguard Worker     return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
6343*61046927SAndroid Build Coastguard Worker }
6344*61046927SAndroid Build Coastguard Worker 
SetCursorPos(const ImVec2 & local_pos)6345*61046927SAndroid Build Coastguard Worker void ImGui::SetCursorPos(const ImVec2& local_pos)
6346*61046927SAndroid Build Coastguard Worker {
6347*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6348*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
6349*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6350*61046927SAndroid Build Coastguard Worker }
6351*61046927SAndroid Build Coastguard Worker 
SetCursorPosX(float x)6352*61046927SAndroid Build Coastguard Worker void ImGui::SetCursorPosX(float x)
6353*61046927SAndroid Build Coastguard Worker {
6354*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6355*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
6356*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
6357*61046927SAndroid Build Coastguard Worker }
6358*61046927SAndroid Build Coastguard Worker 
SetCursorPosY(float y)6359*61046927SAndroid Build Coastguard Worker void ImGui::SetCursorPosY(float y)
6360*61046927SAndroid Build Coastguard Worker {
6361*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6362*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
6363*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
6364*61046927SAndroid Build Coastguard Worker }
6365*61046927SAndroid Build Coastguard Worker 
GetCursorStartPos()6366*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetCursorStartPos()
6367*61046927SAndroid Build Coastguard Worker {
6368*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6369*61046927SAndroid Build Coastguard Worker     return window->DC.CursorStartPos - window->Pos;
6370*61046927SAndroid Build Coastguard Worker }
6371*61046927SAndroid Build Coastguard Worker 
GetCursorScreenPos()6372*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetCursorScreenPos()
6373*61046927SAndroid Build Coastguard Worker {
6374*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
6375*61046927SAndroid Build Coastguard Worker     return window->DC.CursorPos;
6376*61046927SAndroid Build Coastguard Worker }
6377*61046927SAndroid Build Coastguard Worker 
SetCursorScreenPos(const ImVec2 & pos)6378*61046927SAndroid Build Coastguard Worker void ImGui::SetCursorScreenPos(const ImVec2& pos)
6379*61046927SAndroid Build Coastguard Worker {
6380*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6381*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos = pos;
6382*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6383*61046927SAndroid Build Coastguard Worker }
6384*61046927SAndroid Build Coastguard Worker 
GetScrollX()6385*61046927SAndroid Build Coastguard Worker float ImGui::GetScrollX()
6386*61046927SAndroid Build Coastguard Worker {
6387*61046927SAndroid Build Coastguard Worker     return GImGui->CurrentWindow->Scroll.x;
6388*61046927SAndroid Build Coastguard Worker }
6389*61046927SAndroid Build Coastguard Worker 
GetScrollY()6390*61046927SAndroid Build Coastguard Worker float ImGui::GetScrollY()
6391*61046927SAndroid Build Coastguard Worker {
6392*61046927SAndroid Build Coastguard Worker     return GImGui->CurrentWindow->Scroll.y;
6393*61046927SAndroid Build Coastguard Worker }
6394*61046927SAndroid Build Coastguard Worker 
GetScrollMaxX()6395*61046927SAndroid Build Coastguard Worker float ImGui::GetScrollMaxX()
6396*61046927SAndroid Build Coastguard Worker {
6397*61046927SAndroid Build Coastguard Worker     return GetWindowScrollMaxX(GImGui->CurrentWindow);
6398*61046927SAndroid Build Coastguard Worker }
6399*61046927SAndroid Build Coastguard Worker 
GetScrollMaxY()6400*61046927SAndroid Build Coastguard Worker float ImGui::GetScrollMaxY()
6401*61046927SAndroid Build Coastguard Worker {
6402*61046927SAndroid Build Coastguard Worker     return GetWindowScrollMaxY(GImGui->CurrentWindow);
6403*61046927SAndroid Build Coastguard Worker }
6404*61046927SAndroid Build Coastguard Worker 
SetScrollX(float scroll_x)6405*61046927SAndroid Build Coastguard Worker void ImGui::SetScrollX(float scroll_x)
6406*61046927SAndroid Build Coastguard Worker {
6407*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6408*61046927SAndroid Build Coastguard Worker     window->ScrollTarget.x = scroll_x;
6409*61046927SAndroid Build Coastguard Worker     window->ScrollTargetCenterRatio.x = 0.0f;
6410*61046927SAndroid Build Coastguard Worker }
6411*61046927SAndroid Build Coastguard Worker 
SetScrollY(float scroll_y)6412*61046927SAndroid Build Coastguard Worker void ImGui::SetScrollY(float scroll_y)
6413*61046927SAndroid Build Coastguard Worker {
6414*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6415*61046927SAndroid Build Coastguard Worker     window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY
6416*61046927SAndroid Build Coastguard Worker     window->ScrollTargetCenterRatio.y = 0.0f;
6417*61046927SAndroid Build Coastguard Worker }
6418*61046927SAndroid Build Coastguard Worker 
SetScrollFromPosY(float local_y,float center_y_ratio)6419*61046927SAndroid Build Coastguard Worker void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
6420*61046927SAndroid Build Coastguard Worker {
6421*61046927SAndroid Build Coastguard Worker     // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
6422*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6423*61046927SAndroid Build Coastguard Worker     IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
6424*61046927SAndroid Build Coastguard Worker     window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y);
6425*61046927SAndroid Build Coastguard Worker     window->ScrollTargetCenterRatio.y = center_y_ratio;
6426*61046927SAndroid Build Coastguard Worker }
6427*61046927SAndroid Build Coastguard Worker 
6428*61046927SAndroid Build Coastguard Worker // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
SetScrollHereY(float center_y_ratio)6429*61046927SAndroid Build Coastguard Worker void ImGui::SetScrollHereY(float center_y_ratio)
6430*61046927SAndroid Build Coastguard Worker {
6431*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6432*61046927SAndroid Build Coastguard Worker     float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space
6433*61046927SAndroid Build Coastguard Worker     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.
6434*61046927SAndroid Build Coastguard Worker     SetScrollFromPosY(target_y, center_y_ratio);
6435*61046927SAndroid Build Coastguard Worker }
6436*61046927SAndroid Build Coastguard Worker 
ActivateItem(ImGuiID id)6437*61046927SAndroid Build Coastguard Worker void ImGui::ActivateItem(ImGuiID id)
6438*61046927SAndroid Build Coastguard Worker {
6439*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6440*61046927SAndroid Build Coastguard Worker     g.NavNextActivateId = id;
6441*61046927SAndroid Build Coastguard Worker }
6442*61046927SAndroid Build Coastguard Worker 
SetKeyboardFocusHere(int offset)6443*61046927SAndroid Build Coastguard Worker void ImGui::SetKeyboardFocusHere(int offset)
6444*61046927SAndroid Build Coastguard Worker {
6445*61046927SAndroid Build Coastguard Worker     IM_ASSERT(offset >= -1);    // -1 is allowed but not below
6446*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6447*61046927SAndroid Build Coastguard Worker     window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
6448*61046927SAndroid Build Coastguard Worker     window->FocusIdxTabRequestNext = INT_MAX;
6449*61046927SAndroid Build Coastguard Worker }
6450*61046927SAndroid Build Coastguard Worker 
SetItemDefaultFocus()6451*61046927SAndroid Build Coastguard Worker void ImGui::SetItemDefaultFocus()
6452*61046927SAndroid Build Coastguard Worker {
6453*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6454*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
6455*61046927SAndroid Build Coastguard Worker     if (!window->Appearing)
6456*61046927SAndroid Build Coastguard Worker         return;
6457*61046927SAndroid Build Coastguard Worker     if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent)
6458*61046927SAndroid Build Coastguard Worker     {
6459*61046927SAndroid Build Coastguard Worker         g.NavInitRequest = false;
6460*61046927SAndroid Build Coastguard Worker         g.NavInitResultId = g.NavWindow->DC.LastItemId;
6461*61046927SAndroid Build Coastguard Worker         g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos);
6462*61046927SAndroid Build Coastguard Worker         NavUpdateAnyRequestFlag();
6463*61046927SAndroid Build Coastguard Worker         if (!IsItemVisible())
6464*61046927SAndroid Build Coastguard Worker             SetScrollHereY();
6465*61046927SAndroid Build Coastguard Worker     }
6466*61046927SAndroid Build Coastguard Worker }
6467*61046927SAndroid Build Coastguard Worker 
SetStateStorage(ImGuiStorage * tree)6468*61046927SAndroid Build Coastguard Worker void ImGui::SetStateStorage(ImGuiStorage* tree)
6469*61046927SAndroid Build Coastguard Worker {
6470*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6471*61046927SAndroid Build Coastguard Worker     window->DC.StateStorage = tree ? tree : &window->StateStorage;
6472*61046927SAndroid Build Coastguard Worker }
6473*61046927SAndroid Build Coastguard Worker 
GetStateStorage()6474*61046927SAndroid Build Coastguard Worker ImGuiStorage* ImGui::GetStateStorage()
6475*61046927SAndroid Build Coastguard Worker {
6476*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6477*61046927SAndroid Build Coastguard Worker     return window->DC.StateStorage;
6478*61046927SAndroid Build Coastguard Worker }
6479*61046927SAndroid Build Coastguard Worker 
PushID(const char * str_id)6480*61046927SAndroid Build Coastguard Worker void ImGui::PushID(const char* str_id)
6481*61046927SAndroid Build Coastguard Worker {
6482*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6483*61046927SAndroid Build Coastguard Worker     window->IDStack.push_back(window->GetIDNoKeepAlive(str_id));
6484*61046927SAndroid Build Coastguard Worker }
6485*61046927SAndroid Build Coastguard Worker 
PushID(const char * str_id_begin,const char * str_id_end)6486*61046927SAndroid Build Coastguard Worker void ImGui::PushID(const char* str_id_begin, const char* str_id_end)
6487*61046927SAndroid Build Coastguard Worker {
6488*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6489*61046927SAndroid Build Coastguard Worker     window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end));
6490*61046927SAndroid Build Coastguard Worker }
6491*61046927SAndroid Build Coastguard Worker 
PushID(const void * ptr_id)6492*61046927SAndroid Build Coastguard Worker void ImGui::PushID(const void* ptr_id)
6493*61046927SAndroid Build Coastguard Worker {
6494*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6495*61046927SAndroid Build Coastguard Worker     window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6496*61046927SAndroid Build Coastguard Worker }
6497*61046927SAndroid Build Coastguard Worker 
PushID(int int_id)6498*61046927SAndroid Build Coastguard Worker void ImGui::PushID(int int_id)
6499*61046927SAndroid Build Coastguard Worker {
6500*61046927SAndroid Build Coastguard Worker     const void* ptr_id = (void*)(intptr_t)int_id;
6501*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6502*61046927SAndroid Build Coastguard Worker     window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6503*61046927SAndroid Build Coastguard Worker }
6504*61046927SAndroid Build Coastguard Worker 
PopID()6505*61046927SAndroid Build Coastguard Worker void ImGui::PopID()
6506*61046927SAndroid Build Coastguard Worker {
6507*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6508*61046927SAndroid Build Coastguard Worker     window->IDStack.pop_back();
6509*61046927SAndroid Build Coastguard Worker }
6510*61046927SAndroid Build Coastguard Worker 
GetID(const char * str_id)6511*61046927SAndroid Build Coastguard Worker ImGuiID ImGui::GetID(const char* str_id)
6512*61046927SAndroid Build Coastguard Worker {
6513*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6514*61046927SAndroid Build Coastguard Worker     return window->GetID(str_id);
6515*61046927SAndroid Build Coastguard Worker }
6516*61046927SAndroid Build Coastguard Worker 
GetID(const char * str_id_begin,const char * str_id_end)6517*61046927SAndroid Build Coastguard Worker ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)
6518*61046927SAndroid Build Coastguard Worker {
6519*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6520*61046927SAndroid Build Coastguard Worker     return window->GetID(str_id_begin, str_id_end);
6521*61046927SAndroid Build Coastguard Worker }
6522*61046927SAndroid Build Coastguard Worker 
GetID(const void * ptr_id)6523*61046927SAndroid Build Coastguard Worker ImGuiID ImGui::GetID(const void* ptr_id)
6524*61046927SAndroid Build Coastguard Worker {
6525*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6526*61046927SAndroid Build Coastguard Worker     return window->GetID(ptr_id);
6527*61046927SAndroid Build Coastguard Worker }
6528*61046927SAndroid Build Coastguard Worker 
IsRectVisible(const ImVec2 & size)6529*61046927SAndroid Build Coastguard Worker bool ImGui::IsRectVisible(const ImVec2& size)
6530*61046927SAndroid Build Coastguard Worker {
6531*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;;
6532*61046927SAndroid Build Coastguard Worker     return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
6533*61046927SAndroid Build Coastguard Worker }
6534*61046927SAndroid Build Coastguard Worker 
IsRectVisible(const ImVec2 & rect_min,const ImVec2 & rect_max)6535*61046927SAndroid Build Coastguard Worker bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
6536*61046927SAndroid Build Coastguard Worker {
6537*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;;
6538*61046927SAndroid Build Coastguard Worker     return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
6539*61046927SAndroid Build Coastguard Worker }
6540*61046927SAndroid Build Coastguard Worker 
6541*61046927SAndroid Build Coastguard Worker // 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.)
BeginGroup()6542*61046927SAndroid Build Coastguard Worker void ImGui::BeginGroup()
6543*61046927SAndroid Build Coastguard Worker {
6544*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6545*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6546*61046927SAndroid Build Coastguard Worker 
6547*61046927SAndroid Build Coastguard Worker     window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
6548*61046927SAndroid Build Coastguard Worker     ImGuiGroupData& group_data = window->DC.GroupStack.back();
6549*61046927SAndroid Build Coastguard Worker     group_data.BackupCursorPos = window->DC.CursorPos;
6550*61046927SAndroid Build Coastguard Worker     group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
6551*61046927SAndroid Build Coastguard Worker     group_data.BackupIndent = window->DC.Indent;
6552*61046927SAndroid Build Coastguard Worker     group_data.BackupGroupOffset = window->DC.GroupOffset;
6553*61046927SAndroid Build Coastguard Worker     group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
6554*61046927SAndroid Build Coastguard Worker     group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
6555*61046927SAndroid Build Coastguard Worker     group_data.BackupLogLinePosY = window->DC.LogLinePosY;
6556*61046927SAndroid Build Coastguard Worker     group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
6557*61046927SAndroid Build Coastguard Worker     group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
6558*61046927SAndroid Build Coastguard Worker     group_data.AdvanceCursor = true;
6559*61046927SAndroid Build Coastguard Worker 
6560*61046927SAndroid Build Coastguard Worker     window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
6561*61046927SAndroid Build Coastguard Worker     window->DC.Indent = window->DC.GroupOffset;
6562*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos = window->DC.CursorPos;
6563*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
6564*61046927SAndroid Build Coastguard Worker     window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6565*61046927SAndroid Build Coastguard Worker }
6566*61046927SAndroid Build Coastguard Worker 
EndGroup()6567*61046927SAndroid Build Coastguard Worker void ImGui::EndGroup()
6568*61046927SAndroid Build Coastguard Worker {
6569*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6570*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6571*61046927SAndroid Build Coastguard Worker     IM_ASSERT(!window->DC.GroupStack.empty());    // Mismatched BeginGroup()/EndGroup() calls
6572*61046927SAndroid Build Coastguard Worker 
6573*61046927SAndroid Build Coastguard Worker     ImGuiGroupData& group_data = window->DC.GroupStack.back();
6574*61046927SAndroid Build Coastguard Worker 
6575*61046927SAndroid Build Coastguard Worker     ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
6576*61046927SAndroid Build Coastguard Worker     group_bb.Max = ImMax(group_bb.Min, group_bb.Max);
6577*61046927SAndroid Build Coastguard Worker 
6578*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos = group_data.BackupCursorPos;
6579*61046927SAndroid Build Coastguard Worker     window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
6580*61046927SAndroid Build Coastguard Worker     window->DC.Indent = group_data.BackupIndent;
6581*61046927SAndroid Build Coastguard Worker     window->DC.GroupOffset = group_data.BackupGroupOffset;
6582*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
6583*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
6584*61046927SAndroid Build Coastguard Worker     window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6585*61046927SAndroid Build Coastguard Worker 
6586*61046927SAndroid Build Coastguard Worker     if (group_data.AdvanceCursor)
6587*61046927SAndroid Build Coastguard Worker     {
6588*61046927SAndroid Build Coastguard Worker         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.
6589*61046927SAndroid Build Coastguard Worker         ItemSize(group_bb.GetSize(), 0.0f);
6590*61046927SAndroid Build Coastguard Worker         ItemAdd(group_bb, 0);
6591*61046927SAndroid Build Coastguard Worker     }
6592*61046927SAndroid Build Coastguard Worker 
6593*61046927SAndroid Build Coastguard Worker     // 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.
6594*61046927SAndroid Build Coastguard Worker     // 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.
6595*61046927SAndroid Build Coastguard Worker     // (and if you grep for LastItemId you'll notice it is only used in that context.
6596*61046927SAndroid Build Coastguard Worker     if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
6597*61046927SAndroid Build Coastguard Worker         window->DC.LastItemId = g.ActiveId;
6598*61046927SAndroid Build Coastguard Worker     else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
6599*61046927SAndroid Build Coastguard Worker         window->DC.LastItemId = g.ActiveIdPreviousFrame;
6600*61046927SAndroid Build Coastguard Worker     window->DC.LastItemRect = group_bb;
6601*61046927SAndroid Build Coastguard Worker 
6602*61046927SAndroid Build Coastguard Worker     window->DC.GroupStack.pop_back();
6603*61046927SAndroid Build Coastguard Worker 
6604*61046927SAndroid Build Coastguard Worker     //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255));   // [Debug]
6605*61046927SAndroid Build Coastguard Worker }
6606*61046927SAndroid Build Coastguard Worker 
6607*61046927SAndroid Build Coastguard Worker // Gets back to previous line and continue with horizontal layout
6608*61046927SAndroid Build Coastguard Worker //      pos_x == 0      : follow right after previous item
6609*61046927SAndroid Build Coastguard Worker //      pos_x != 0      : align to specified x position (relative to window/group left)
6610*61046927SAndroid Build Coastguard Worker //      spacing_w < 0   : use default spacing if pos_x == 0, no spacing if pos_x != 0
6611*61046927SAndroid Build Coastguard Worker //      spacing_w >= 0  : enforce spacing amount
SameLine(float pos_x,float spacing_w)6612*61046927SAndroid Build Coastguard Worker void ImGui::SameLine(float pos_x, float spacing_w)
6613*61046927SAndroid Build Coastguard Worker {
6614*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6615*61046927SAndroid Build Coastguard Worker     if (window->SkipItems)
6616*61046927SAndroid Build Coastguard Worker         return;
6617*61046927SAndroid Build Coastguard Worker 
6618*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6619*61046927SAndroid Build Coastguard Worker     if (pos_x != 0.0f)
6620*61046927SAndroid Build Coastguard Worker     {
6621*61046927SAndroid Build Coastguard Worker         if (spacing_w < 0.0f) spacing_w = 0.0f;
6622*61046927SAndroid Build Coastguard Worker         window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
6623*61046927SAndroid Build Coastguard Worker         window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6624*61046927SAndroid Build Coastguard Worker     }
6625*61046927SAndroid Build Coastguard Worker     else
6626*61046927SAndroid Build Coastguard Worker     {
6627*61046927SAndroid Build Coastguard Worker         if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;
6628*61046927SAndroid Build Coastguard Worker         window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
6629*61046927SAndroid Build Coastguard Worker         window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6630*61046927SAndroid Build Coastguard Worker     }
6631*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineSize = window->DC.PrevLineSize;
6632*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
6633*61046927SAndroid Build Coastguard Worker }
6634*61046927SAndroid Build Coastguard Worker 
Indent(float indent_w)6635*61046927SAndroid Build Coastguard Worker void ImGui::Indent(float indent_w)
6636*61046927SAndroid Build Coastguard Worker {
6637*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6638*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6639*61046927SAndroid Build Coastguard Worker     window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6640*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6641*61046927SAndroid Build Coastguard Worker }
6642*61046927SAndroid Build Coastguard Worker 
Unindent(float indent_w)6643*61046927SAndroid Build Coastguard Worker void ImGui::Unindent(float indent_w)
6644*61046927SAndroid Build Coastguard Worker {
6645*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6646*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
6647*61046927SAndroid Build Coastguard Worker     window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6648*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6649*61046927SAndroid Build Coastguard Worker }
6650*61046927SAndroid Build Coastguard Worker 
6651*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
6652*61046927SAndroid Build Coastguard Worker // [SECTION] TOOLTIPS
6653*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
6654*61046927SAndroid Build Coastguard Worker 
BeginTooltip()6655*61046927SAndroid Build Coastguard Worker void ImGui::BeginTooltip()
6656*61046927SAndroid Build Coastguard Worker {
6657*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6658*61046927SAndroid Build Coastguard Worker     if (g.DragDropWithinSourceOrTarget)
6659*61046927SAndroid Build Coastguard Worker     {
6660*61046927SAndroid Build Coastguard Worker         // 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)
6661*61046927SAndroid Build Coastguard Worker         // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor.
6662*61046927SAndroid Build Coastguard Worker         // 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.
6663*61046927SAndroid Build Coastguard Worker         //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
6664*61046927SAndroid Build Coastguard Worker         ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale);
6665*61046927SAndroid Build Coastguard Worker         SetNextWindowPos(tooltip_pos);
6666*61046927SAndroid Build Coastguard Worker         SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
6667*61046927SAndroid Build Coastguard Worker         //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
6668*61046927SAndroid Build Coastguard Worker         BeginTooltipEx(0, true);
6669*61046927SAndroid Build Coastguard Worker     }
6670*61046927SAndroid Build Coastguard Worker     else
6671*61046927SAndroid Build Coastguard Worker     {
6672*61046927SAndroid Build Coastguard Worker         BeginTooltipEx(0, false);
6673*61046927SAndroid Build Coastguard Worker     }
6674*61046927SAndroid Build Coastguard Worker }
6675*61046927SAndroid Build Coastguard Worker 
6676*61046927SAndroid Build Coastguard Worker // Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first.
BeginTooltipEx(ImGuiWindowFlags extra_flags,bool override_previous_tooltip)6677*61046927SAndroid Build Coastguard Worker void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip)
6678*61046927SAndroid Build Coastguard Worker {
6679*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6680*61046927SAndroid Build Coastguard Worker     char window_name[16];
6681*61046927SAndroid Build Coastguard Worker     ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
6682*61046927SAndroid Build Coastguard Worker     if (override_previous_tooltip)
6683*61046927SAndroid Build Coastguard Worker         if (ImGuiWindow* window = FindWindowByName(window_name))
6684*61046927SAndroid Build Coastguard Worker             if (window->Active)
6685*61046927SAndroid Build Coastguard Worker             {
6686*61046927SAndroid Build Coastguard Worker                 // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
6687*61046927SAndroid Build Coastguard Worker                 window->Hidden = true;
6688*61046927SAndroid Build Coastguard Worker                 window->HiddenFramesRegular = 1;
6689*61046927SAndroid Build Coastguard Worker                 ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
6690*61046927SAndroid Build Coastguard Worker             }
6691*61046927SAndroid Build Coastguard Worker     ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
6692*61046927SAndroid Build Coastguard Worker     Begin(window_name, NULL, flags | extra_flags);
6693*61046927SAndroid Build Coastguard Worker }
6694*61046927SAndroid Build Coastguard Worker 
EndTooltip()6695*61046927SAndroid Build Coastguard Worker void ImGui::EndTooltip()
6696*61046927SAndroid Build Coastguard Worker {
6697*61046927SAndroid Build Coastguard Worker     IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);   // Mismatched BeginTooltip()/EndTooltip() calls
6698*61046927SAndroid Build Coastguard Worker     End();
6699*61046927SAndroid Build Coastguard Worker }
6700*61046927SAndroid Build Coastguard Worker 
SetTooltipV(const char * fmt,va_list args)6701*61046927SAndroid Build Coastguard Worker void ImGui::SetTooltipV(const char* fmt, va_list args)
6702*61046927SAndroid Build Coastguard Worker {
6703*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6704*61046927SAndroid Build Coastguard Worker     if (g.DragDropWithinSourceOrTarget)
6705*61046927SAndroid Build Coastguard Worker         BeginTooltip();
6706*61046927SAndroid Build Coastguard Worker     else
6707*61046927SAndroid Build Coastguard Worker         BeginTooltipEx(0, true);
6708*61046927SAndroid Build Coastguard Worker     TextV(fmt, args);
6709*61046927SAndroid Build Coastguard Worker     EndTooltip();
6710*61046927SAndroid Build Coastguard Worker }
6711*61046927SAndroid Build Coastguard Worker 
SetTooltip(const char * fmt,...)6712*61046927SAndroid Build Coastguard Worker void ImGui::SetTooltip(const char* fmt, ...)
6713*61046927SAndroid Build Coastguard Worker {
6714*61046927SAndroid Build Coastguard Worker     va_list args;
6715*61046927SAndroid Build Coastguard Worker     va_start(args, fmt);
6716*61046927SAndroid Build Coastguard Worker     SetTooltipV(fmt, args);
6717*61046927SAndroid Build Coastguard Worker     va_end(args);
6718*61046927SAndroid Build Coastguard Worker }
6719*61046927SAndroid Build Coastguard Worker 
6720*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
6721*61046927SAndroid Build Coastguard Worker // [SECTION] POPUPS
6722*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
6723*61046927SAndroid Build Coastguard Worker 
IsPopupOpen(ImGuiID id)6724*61046927SAndroid Build Coastguard Worker bool ImGui::IsPopupOpen(ImGuiID id)
6725*61046927SAndroid Build Coastguard Worker {
6726*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6727*61046927SAndroid Build Coastguard Worker     return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
6728*61046927SAndroid Build Coastguard Worker }
6729*61046927SAndroid Build Coastguard Worker 
IsPopupOpen(const char * str_id)6730*61046927SAndroid Build Coastguard Worker bool ImGui::IsPopupOpen(const char* str_id)
6731*61046927SAndroid Build Coastguard Worker {
6732*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6733*61046927SAndroid Build Coastguard Worker     return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
6734*61046927SAndroid Build Coastguard Worker }
6735*61046927SAndroid Build Coastguard Worker 
GetFrontMostPopupModal()6736*61046927SAndroid Build Coastguard Worker ImGuiWindow* ImGui::GetFrontMostPopupModal()
6737*61046927SAndroid Build Coastguard Worker {
6738*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6739*61046927SAndroid Build Coastguard Worker     for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)
6740*61046927SAndroid Build Coastguard Worker         if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
6741*61046927SAndroid Build Coastguard Worker             if (popup->Flags & ImGuiWindowFlags_Modal)
6742*61046927SAndroid Build Coastguard Worker                 return popup;
6743*61046927SAndroid Build Coastguard Worker     return NULL;
6744*61046927SAndroid Build Coastguard Worker }
6745*61046927SAndroid Build Coastguard Worker 
OpenPopup(const char * str_id)6746*61046927SAndroid Build Coastguard Worker void ImGui::OpenPopup(const char* str_id)
6747*61046927SAndroid Build Coastguard Worker {
6748*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6749*61046927SAndroid Build Coastguard Worker     OpenPopupEx(g.CurrentWindow->GetID(str_id));
6750*61046927SAndroid Build Coastguard Worker }
6751*61046927SAndroid Build Coastguard Worker 
6752*61046927SAndroid Build Coastguard Worker // Mark popup as open (toggle toward open state).
6753*61046927SAndroid Build Coastguard Worker // Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
6754*61046927SAndroid Build Coastguard Worker // Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
6755*61046927SAndroid Build Coastguard Worker // One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
OpenPopupEx(ImGuiID id)6756*61046927SAndroid Build Coastguard Worker void ImGui::OpenPopupEx(ImGuiID id)
6757*61046927SAndroid Build Coastguard Worker {
6758*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6759*61046927SAndroid Build Coastguard Worker     ImGuiWindow* parent_window = g.CurrentWindow;
6760*61046927SAndroid Build Coastguard Worker     int current_stack_size = g.BeginPopupStack.Size;
6761*61046927SAndroid Build Coastguard Worker     ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
6762*61046927SAndroid Build Coastguard Worker     popup_ref.PopupId = id;
6763*61046927SAndroid Build Coastguard Worker     popup_ref.Window = NULL;
6764*61046927SAndroid Build Coastguard Worker     popup_ref.ParentWindow = parent_window;
6765*61046927SAndroid Build Coastguard Worker     popup_ref.OpenFrameCount = g.FrameCount;
6766*61046927SAndroid Build Coastguard Worker     popup_ref.OpenParentId = parent_window->IDStack.back();
6767*61046927SAndroid Build Coastguard Worker     popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
6768*61046927SAndroid Build Coastguard Worker     popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
6769*61046927SAndroid Build Coastguard Worker 
6770*61046927SAndroid Build Coastguard Worker     //IMGUI_DEBUG_LOG("OpenPopupEx(0x%08X)\n", g.FrameCount, id);
6771*61046927SAndroid Build Coastguard Worker     if (g.OpenPopupStack.Size < current_stack_size + 1)
6772*61046927SAndroid Build Coastguard Worker     {
6773*61046927SAndroid Build Coastguard Worker         g.OpenPopupStack.push_back(popup_ref);
6774*61046927SAndroid Build Coastguard Worker     }
6775*61046927SAndroid Build Coastguard Worker     else
6776*61046927SAndroid Build Coastguard Worker     {
6777*61046927SAndroid Build Coastguard Worker         // 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
6778*61046927SAndroid Build Coastguard Worker         // 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
6779*61046927SAndroid Build Coastguard Worker         // 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.
6780*61046927SAndroid Build Coastguard Worker         if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1)
6781*61046927SAndroid Build Coastguard Worker         {
6782*61046927SAndroid Build Coastguard Worker             g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
6783*61046927SAndroid Build Coastguard Worker         }
6784*61046927SAndroid Build Coastguard Worker         else
6785*61046927SAndroid Build Coastguard Worker         {
6786*61046927SAndroid Build Coastguard Worker             // Close child popups if any, then flag popup for open/reopen
6787*61046927SAndroid Build Coastguard Worker             g.OpenPopupStack.resize(current_stack_size + 1);
6788*61046927SAndroid Build Coastguard Worker             g.OpenPopupStack[current_stack_size] = popup_ref;
6789*61046927SAndroid Build Coastguard Worker         }
6790*61046927SAndroid Build Coastguard Worker 
6791*61046927SAndroid Build Coastguard Worker         // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
6792*61046927SAndroid Build Coastguard Worker         // This is equivalent to what ClosePopupToLevel() does.
6793*61046927SAndroid Build Coastguard Worker         //if (g.OpenPopupStack[current_stack_size].PopupId == id)
6794*61046927SAndroid Build Coastguard Worker         //    FocusWindow(parent_window);
6795*61046927SAndroid Build Coastguard Worker     }
6796*61046927SAndroid Build Coastguard Worker }
6797*61046927SAndroid Build Coastguard Worker 
OpenPopupOnItemClick(const char * str_id,int mouse_button)6798*61046927SAndroid Build Coastguard Worker bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button)
6799*61046927SAndroid Build Coastguard Worker {
6800*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6801*61046927SAndroid Build Coastguard Worker     if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
6802*61046927SAndroid Build Coastguard Worker     {
6803*61046927SAndroid Build Coastguard Worker         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!
6804*61046927SAndroid Build Coastguard Worker         IM_ASSERT(id != 0);                                                  // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
6805*61046927SAndroid Build Coastguard Worker         OpenPopupEx(id);
6806*61046927SAndroid Build Coastguard Worker         return true;
6807*61046927SAndroid Build Coastguard Worker     }
6808*61046927SAndroid Build Coastguard Worker     return false;
6809*61046927SAndroid Build Coastguard Worker }
6810*61046927SAndroid Build Coastguard Worker 
ClosePopupsOverWindow(ImGuiWindow * ref_window)6811*61046927SAndroid Build Coastguard Worker void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window)
6812*61046927SAndroid Build Coastguard Worker {
6813*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6814*61046927SAndroid Build Coastguard Worker     if (g.OpenPopupStack.empty())
6815*61046927SAndroid Build Coastguard Worker         return;
6816*61046927SAndroid Build Coastguard Worker 
6817*61046927SAndroid Build Coastguard Worker     // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
6818*61046927SAndroid Build Coastguard Worker     // Don't close our own child popup windows.
6819*61046927SAndroid Build Coastguard Worker     int popup_count_to_keep = 0;
6820*61046927SAndroid Build Coastguard Worker     if (ref_window)
6821*61046927SAndroid Build Coastguard Worker     {
6822*61046927SAndroid Build Coastguard Worker         // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
6823*61046927SAndroid Build Coastguard Worker         for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
6824*61046927SAndroid Build Coastguard Worker         {
6825*61046927SAndroid Build Coastguard Worker             ImGuiPopupRef& popup = g.OpenPopupStack[popup_count_to_keep];
6826*61046927SAndroid Build Coastguard Worker             if (!popup.Window)
6827*61046927SAndroid Build Coastguard Worker                 continue;
6828*61046927SAndroid Build Coastguard Worker             IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
6829*61046927SAndroid Build Coastguard Worker             if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
6830*61046927SAndroid Build Coastguard Worker                 continue;
6831*61046927SAndroid Build Coastguard Worker 
6832*61046927SAndroid Build Coastguard Worker             // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow)
6833*61046927SAndroid Build Coastguard Worker             bool popup_or_descendent_has_focus = false;
6834*61046927SAndroid Build Coastguard Worker             for (int m = popup_count_to_keep; m < g.OpenPopupStack.Size && !popup_or_descendent_has_focus; m++)
6835*61046927SAndroid Build Coastguard Worker                 if (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow)
6836*61046927SAndroid Build Coastguard Worker                     popup_or_descendent_has_focus = true;
6837*61046927SAndroid Build Coastguard Worker             if (!popup_or_descendent_has_focus)
6838*61046927SAndroid Build Coastguard Worker                 break;
6839*61046927SAndroid Build Coastguard Worker         }
6840*61046927SAndroid Build Coastguard Worker     }
6841*61046927SAndroid Build Coastguard Worker     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
6842*61046927SAndroid Build Coastguard Worker     {
6843*61046927SAndroid Build Coastguard Worker         //IMGUI_DEBUG_LOG("ClosePopupsOverWindow(%s) -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
6844*61046927SAndroid Build Coastguard Worker         ClosePopupToLevel(popup_count_to_keep, false);
6845*61046927SAndroid Build Coastguard Worker     }
6846*61046927SAndroid Build Coastguard Worker }
6847*61046927SAndroid Build Coastguard Worker 
ClosePopupToLevel(int remaining,bool apply_focus_to_window_under)6848*61046927SAndroid Build Coastguard Worker void ImGui::ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
6849*61046927SAndroid Build Coastguard Worker {
6850*61046927SAndroid Build Coastguard Worker     IM_ASSERT(remaining >= 0);
6851*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6852*61046927SAndroid Build Coastguard Worker     ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow;
6853*61046927SAndroid Build Coastguard Worker     g.OpenPopupStack.resize(remaining);
6854*61046927SAndroid Build Coastguard Worker 
6855*61046927SAndroid Build Coastguard Worker     // FIXME: This code is faulty and we may want to eventually to replace or remove the 'apply_focus_to_window_under=true' path completely.
6856*61046927SAndroid Build Coastguard Worker     // Instead of using g.OpenPopupStack[remaining-1].Window etc. we should find the highest root window that is behind the popups we are closing.
6857*61046927SAndroid Build Coastguard Worker     // The current code will set focus to the parent of the popup window which is incorrect.
6858*61046927SAndroid Build Coastguard Worker     // It rarely manifested until now because UpdateMouseMovingWindowNewFrame() would call FocusWindow() again on the clicked window,
6859*61046927SAndroid Build Coastguard Worker     // leading to a chain of focusing A (clicked window) then B (parent window of the popup) then A again.
6860*61046927SAndroid Build Coastguard Worker     // However if the clicked window has the _NoMove flag set we would be left with B focused.
6861*61046927SAndroid Build Coastguard Worker     // For now, we have disabled this path when called from ClosePopupsOverWindow() because the users of ClosePopupsOverWindow() don't need to alter focus anyway,
6862*61046927SAndroid Build Coastguard Worker     // but we should inspect and fix this properly.
6863*61046927SAndroid Build Coastguard Worker     if (apply_focus_to_window_under)
6864*61046927SAndroid Build Coastguard Worker     {
6865*61046927SAndroid Build Coastguard Worker         if (g.NavLayer == 0)
6866*61046927SAndroid Build Coastguard Worker             focus_window = NavRestoreLastChildNavWindow(focus_window);
6867*61046927SAndroid Build Coastguard Worker         FocusWindow(focus_window);
6868*61046927SAndroid Build Coastguard Worker     }
6869*61046927SAndroid Build Coastguard Worker }
6870*61046927SAndroid Build Coastguard Worker 
6871*61046927SAndroid Build Coastguard Worker // Close the popup we have begin-ed into.
CloseCurrentPopup()6872*61046927SAndroid Build Coastguard Worker void ImGui::CloseCurrentPopup()
6873*61046927SAndroid Build Coastguard Worker {
6874*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6875*61046927SAndroid Build Coastguard Worker     int popup_idx = g.BeginPopupStack.Size - 1;
6876*61046927SAndroid Build Coastguard Worker     if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
6877*61046927SAndroid Build Coastguard Worker         return;
6878*61046927SAndroid Build Coastguard Worker 
6879*61046927SAndroid Build Coastguard Worker     // Closing a menu closes its top-most parent popup (unless a modal)
6880*61046927SAndroid Build Coastguard Worker     while (popup_idx > 0)
6881*61046927SAndroid Build Coastguard Worker     {
6882*61046927SAndroid Build Coastguard Worker         ImGuiWindow* popup_window = g.OpenPopupStack[popup_idx].Window;
6883*61046927SAndroid Build Coastguard Worker         ImGuiWindow* parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window;
6884*61046927SAndroid Build Coastguard Worker         bool close_parent = false;
6885*61046927SAndroid Build Coastguard Worker         if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
6886*61046927SAndroid Build Coastguard Worker             if (parent_popup_window == NULL || !(parent_popup_window->Flags & ImGuiWindowFlags_Modal))
6887*61046927SAndroid Build Coastguard Worker                 close_parent = true;
6888*61046927SAndroid Build Coastguard Worker         if (!close_parent)
6889*61046927SAndroid Build Coastguard Worker             break;
6890*61046927SAndroid Build Coastguard Worker         popup_idx--;
6891*61046927SAndroid Build Coastguard Worker     }
6892*61046927SAndroid Build Coastguard Worker     //IMGUI_DEBUG_LOG("CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx);
6893*61046927SAndroid Build Coastguard Worker     ClosePopupToLevel(popup_idx, true);
6894*61046927SAndroid Build Coastguard Worker 
6895*61046927SAndroid Build Coastguard Worker     // A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
6896*61046927SAndroid Build Coastguard Worker     // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
6897*61046927SAndroid Build Coastguard Worker     // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
6898*61046927SAndroid Build Coastguard Worker     if (ImGuiWindow* window = g.NavWindow)
6899*61046927SAndroid Build Coastguard Worker         window->DC.NavHideHighlightOneFrame = true;
6900*61046927SAndroid Build Coastguard Worker }
6901*61046927SAndroid Build Coastguard Worker 
BeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_flags)6902*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
6903*61046927SAndroid Build Coastguard Worker {
6904*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6905*61046927SAndroid Build Coastguard Worker     if (!IsPopupOpen(id))
6906*61046927SAndroid Build Coastguard Worker     {
6907*61046927SAndroid Build Coastguard Worker         g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6908*61046927SAndroid Build Coastguard Worker         return false;
6909*61046927SAndroid Build Coastguard Worker     }
6910*61046927SAndroid Build Coastguard Worker 
6911*61046927SAndroid Build Coastguard Worker     char name[20];
6912*61046927SAndroid Build Coastguard Worker     if (extra_flags & ImGuiWindowFlags_ChildMenu)
6913*61046927SAndroid Build Coastguard Worker         ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
6914*61046927SAndroid Build Coastguard Worker     else
6915*61046927SAndroid Build Coastguard Worker         ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
6916*61046927SAndroid Build Coastguard Worker 
6917*61046927SAndroid Build Coastguard Worker     bool is_open = Begin(name, NULL, extra_flags | ImGuiWindowFlags_Popup);
6918*61046927SAndroid Build Coastguard Worker     if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
6919*61046927SAndroid Build Coastguard Worker         EndPopup();
6920*61046927SAndroid Build Coastguard Worker 
6921*61046927SAndroid Build Coastguard Worker     return is_open;
6922*61046927SAndroid Build Coastguard Worker }
6923*61046927SAndroid Build Coastguard Worker 
BeginPopup(const char * str_id,ImGuiWindowFlags flags)6924*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
6925*61046927SAndroid Build Coastguard Worker {
6926*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6927*61046927SAndroid Build Coastguard Worker     if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
6928*61046927SAndroid Build Coastguard Worker     {
6929*61046927SAndroid Build Coastguard Worker         g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6930*61046927SAndroid Build Coastguard Worker         return false;
6931*61046927SAndroid Build Coastguard Worker     }
6932*61046927SAndroid Build Coastguard Worker     flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
6933*61046927SAndroid Build Coastguard Worker     return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags);
6934*61046927SAndroid Build Coastguard Worker }
6935*61046927SAndroid Build Coastguard Worker 
6936*61046927SAndroid Build Coastguard Worker // If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
6937*61046927SAndroid Build Coastguard Worker // 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.
BeginPopupModal(const char * name,bool * p_open,ImGuiWindowFlags flags)6938*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags)
6939*61046927SAndroid Build Coastguard Worker {
6940*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6941*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
6942*61046927SAndroid Build Coastguard Worker     const ImGuiID id = window->GetID(name);
6943*61046927SAndroid Build Coastguard Worker     if (!IsPopupOpen(id))
6944*61046927SAndroid Build Coastguard Worker     {
6945*61046927SAndroid Build Coastguard Worker         g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
6946*61046927SAndroid Build Coastguard Worker         return false;
6947*61046927SAndroid Build Coastguard Worker     }
6948*61046927SAndroid Build Coastguard Worker 
6949*61046927SAndroid Build Coastguard Worker     // Center modal windows by default
6950*61046927SAndroid Build Coastguard Worker     // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
6951*61046927SAndroid Build Coastguard Worker     if (g.NextWindowData.PosCond == 0)
6952*61046927SAndroid Build Coastguard Worker         SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
6953*61046927SAndroid Build Coastguard Worker 
6954*61046927SAndroid Build Coastguard Worker     flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings;
6955*61046927SAndroid Build Coastguard Worker     const bool is_open = Begin(name, p_open, flags);
6956*61046927SAndroid Build Coastguard Worker     if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
6957*61046927SAndroid Build Coastguard Worker     {
6958*61046927SAndroid Build Coastguard Worker         EndPopup();
6959*61046927SAndroid Build Coastguard Worker         if (is_open)
6960*61046927SAndroid Build Coastguard Worker             ClosePopupToLevel(g.BeginPopupStack.Size, true);
6961*61046927SAndroid Build Coastguard Worker         return false;
6962*61046927SAndroid Build Coastguard Worker     }
6963*61046927SAndroid Build Coastguard Worker     return is_open;
6964*61046927SAndroid Build Coastguard Worker }
6965*61046927SAndroid Build Coastguard Worker 
EndPopup()6966*61046927SAndroid Build Coastguard Worker void ImGui::EndPopup()
6967*61046927SAndroid Build Coastguard Worker {
6968*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
6969*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup);  // Mismatched BeginPopup()/EndPopup() calls
6970*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.BeginPopupStack.Size > 0);
6971*61046927SAndroid Build Coastguard Worker 
6972*61046927SAndroid Build Coastguard Worker     // Make all menus and popups wrap around for now, may need to expose that policy.
6973*61046927SAndroid Build Coastguard Worker     NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY);
6974*61046927SAndroid Build Coastguard Worker 
6975*61046927SAndroid Build Coastguard Worker     End();
6976*61046927SAndroid Build Coastguard Worker }
6977*61046927SAndroid Build Coastguard Worker 
6978*61046927SAndroid Build Coastguard Worker // This is a helper to handle the simplest case of associating one named popup to one given widget.
6979*61046927SAndroid Build Coastguard Worker // You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
6980*61046927SAndroid Build Coastguard Worker // You can pass a NULL str_id to use the identifier of the last item.
BeginPopupContextItem(const char * str_id,int mouse_button)6981*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button)
6982*61046927SAndroid Build Coastguard Worker {
6983*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GImGui->CurrentWindow;
6984*61046927SAndroid Build Coastguard Worker     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!
6985*61046927SAndroid Build Coastguard Worker     IM_ASSERT(id != 0);                                                  // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
6986*61046927SAndroid Build Coastguard Worker     if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
6987*61046927SAndroid Build Coastguard Worker         OpenPopupEx(id);
6988*61046927SAndroid Build Coastguard Worker     return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
6989*61046927SAndroid Build Coastguard Worker }
6990*61046927SAndroid Build Coastguard Worker 
BeginPopupContextWindow(const char * str_id,int mouse_button,bool also_over_items)6991*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items)
6992*61046927SAndroid Build Coastguard Worker {
6993*61046927SAndroid Build Coastguard Worker     if (!str_id)
6994*61046927SAndroid Build Coastguard Worker         str_id = "window_context";
6995*61046927SAndroid Build Coastguard Worker     ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
6996*61046927SAndroid Build Coastguard Worker     if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
6997*61046927SAndroid Build Coastguard Worker         if (also_over_items || !IsAnyItemHovered())
6998*61046927SAndroid Build Coastguard Worker             OpenPopupEx(id);
6999*61046927SAndroid Build Coastguard Worker     return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
7000*61046927SAndroid Build Coastguard Worker }
7001*61046927SAndroid Build Coastguard Worker 
BeginPopupContextVoid(const char * str_id,int mouse_button)7002*61046927SAndroid Build Coastguard Worker bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
7003*61046927SAndroid Build Coastguard Worker {
7004*61046927SAndroid Build Coastguard Worker     if (!str_id)
7005*61046927SAndroid Build Coastguard Worker         str_id = "void_context";
7006*61046927SAndroid Build Coastguard Worker     ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
7007*61046927SAndroid Build Coastguard Worker     if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
7008*61046927SAndroid Build Coastguard Worker         OpenPopupEx(id);
7009*61046927SAndroid Build Coastguard Worker     return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
7010*61046927SAndroid Build Coastguard Worker }
7011*61046927SAndroid Build Coastguard Worker 
GetWindowAllowedExtentRect(ImGuiWindow *)7012*61046927SAndroid Build Coastguard Worker ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow*)
7013*61046927SAndroid Build Coastguard Worker {
7014*61046927SAndroid Build Coastguard Worker     ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding;
7015*61046927SAndroid Build Coastguard Worker     ImRect r_screen = GetViewportRect();
7016*61046927SAndroid Build Coastguard Worker     r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
7017*61046927SAndroid Build Coastguard Worker     return r_screen;
7018*61046927SAndroid Build Coastguard Worker }
7019*61046927SAndroid Build Coastguard Worker 
7020*61046927SAndroid Build Coastguard Worker // 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.)
7021*61046927SAndroid Build Coastguard Worker // 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.
FindBestWindowPosForPopupEx(const ImVec2 & ref_pos,const ImVec2 & size,ImGuiDir * last_dir,const ImRect & r_outer,const ImRect & r_avoid,ImGuiPopupPositionPolicy policy)7022*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
7023*61046927SAndroid Build Coastguard Worker {
7024*61046927SAndroid Build Coastguard Worker     ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
7025*61046927SAndroid Build Coastguard Worker     //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255));
7026*61046927SAndroid Build Coastguard Worker     //GImGui->OverlayDrawList.AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255));
7027*61046927SAndroid Build Coastguard Worker 
7028*61046927SAndroid Build Coastguard Worker     // Combo Box policy (we want a connecting edge)
7029*61046927SAndroid Build Coastguard Worker     if (policy == ImGuiPopupPositionPolicy_ComboBox)
7030*61046927SAndroid Build Coastguard Worker     {
7031*61046927SAndroid Build Coastguard Worker         const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
7032*61046927SAndroid Build Coastguard Worker         for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
7033*61046927SAndroid Build Coastguard Worker         {
7034*61046927SAndroid Build Coastguard Worker             const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
7035*61046927SAndroid Build Coastguard Worker             if (n != -1 && dir == *last_dir) // Already tried this direction?
7036*61046927SAndroid Build Coastguard Worker                 continue;
7037*61046927SAndroid Build Coastguard Worker             ImVec2 pos;
7038*61046927SAndroid Build Coastguard Worker             if (dir == ImGuiDir_Down)  pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y);          // Below, Toward Right (default)
7039*61046927SAndroid Build Coastguard Worker             if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right
7040*61046927SAndroid Build Coastguard Worker             if (dir == ImGuiDir_Left)  pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left
7041*61046927SAndroid Build Coastguard Worker             if (dir == ImGuiDir_Up)    pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left
7042*61046927SAndroid Build Coastguard Worker             if (!r_outer.Contains(ImRect(pos, pos + size)))
7043*61046927SAndroid Build Coastguard Worker                 continue;
7044*61046927SAndroid Build Coastguard Worker             *last_dir = dir;
7045*61046927SAndroid Build Coastguard Worker             return pos;
7046*61046927SAndroid Build Coastguard Worker         }
7047*61046927SAndroid Build Coastguard Worker     }
7048*61046927SAndroid Build Coastguard Worker 
7049*61046927SAndroid Build Coastguard Worker     // Default popup policy
7050*61046927SAndroid Build Coastguard Worker     const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
7051*61046927SAndroid Build Coastguard Worker     for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
7052*61046927SAndroid Build Coastguard Worker     {
7053*61046927SAndroid Build Coastguard Worker         const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
7054*61046927SAndroid Build Coastguard Worker         if (n != -1 && dir == *last_dir) // Already tried this direction?
7055*61046927SAndroid Build Coastguard Worker             continue;
7056*61046927SAndroid Build Coastguard Worker         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);
7057*61046927SAndroid Build Coastguard Worker         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);
7058*61046927SAndroid Build Coastguard Worker         if (avail_w < size.x || avail_h < size.y)
7059*61046927SAndroid Build Coastguard Worker             continue;
7060*61046927SAndroid Build Coastguard Worker         ImVec2 pos;
7061*61046927SAndroid Build Coastguard Worker         pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
7062*61046927SAndroid Build Coastguard Worker         pos.y = (dir == ImGuiDir_Up)   ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down)  ? r_avoid.Max.y : base_pos_clamped.y;
7063*61046927SAndroid Build Coastguard Worker         *last_dir = dir;
7064*61046927SAndroid Build Coastguard Worker         return pos;
7065*61046927SAndroid Build Coastguard Worker     }
7066*61046927SAndroid Build Coastguard Worker 
7067*61046927SAndroid Build Coastguard Worker     // Fallback, try to keep within display
7068*61046927SAndroid Build Coastguard Worker     *last_dir = ImGuiDir_None;
7069*61046927SAndroid Build Coastguard Worker     ImVec2 pos = ref_pos;
7070*61046927SAndroid Build Coastguard Worker     pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
7071*61046927SAndroid Build Coastguard Worker     pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
7072*61046927SAndroid Build Coastguard Worker     return pos;
7073*61046927SAndroid Build Coastguard Worker }
7074*61046927SAndroid Build Coastguard Worker 
FindBestWindowPosForPopup(ImGuiWindow * window)7075*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
7076*61046927SAndroid Build Coastguard Worker {
7077*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7078*61046927SAndroid Build Coastguard Worker 
7079*61046927SAndroid Build Coastguard Worker     ImRect r_outer = GetWindowAllowedExtentRect(window);
7080*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_ChildMenu)
7081*61046927SAndroid Build Coastguard Worker     {
7082*61046927SAndroid Build Coastguard Worker         // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds.
7083*61046927SAndroid Build Coastguard Worker         // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.
7084*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.CurrentWindow == window);
7085*61046927SAndroid Build Coastguard Worker         ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2];
7086*61046927SAndroid Build Coastguard Worker         float horizontal_overlap = g.Style.ItemInnerSpacing.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).
7087*61046927SAndroid Build Coastguard Worker         ImRect r_avoid;
7088*61046927SAndroid Build Coastguard Worker         if (parent_window->DC.MenuBarAppending)
7089*61046927SAndroid Build Coastguard Worker             r_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight());
7090*61046927SAndroid Build Coastguard Worker         else
7091*61046927SAndroid Build Coastguard Worker             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);
7092*61046927SAndroid Build Coastguard Worker         return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7093*61046927SAndroid Build Coastguard Worker     }
7094*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Popup)
7095*61046927SAndroid Build Coastguard Worker     {
7096*61046927SAndroid Build Coastguard Worker         ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
7097*61046927SAndroid Build Coastguard Worker         return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7098*61046927SAndroid Build Coastguard Worker     }
7099*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Tooltip)
7100*61046927SAndroid Build Coastguard Worker     {
7101*61046927SAndroid Build Coastguard Worker         // Position tooltip (always follows mouse)
7102*61046927SAndroid Build Coastguard Worker         float sc = g.Style.MouseCursorScale;
7103*61046927SAndroid Build Coastguard Worker         ImVec2 ref_pos = NavCalcPreferredRefPos();
7104*61046927SAndroid Build Coastguard Worker         ImRect r_avoid;
7105*61046927SAndroid Build Coastguard Worker         if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
7106*61046927SAndroid Build Coastguard Worker             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
7107*61046927SAndroid Build Coastguard Worker         else
7108*61046927SAndroid Build Coastguard Worker             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.
7109*61046927SAndroid Build Coastguard Worker         ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7110*61046927SAndroid Build Coastguard Worker         if (window->AutoPosLastDirection == ImGuiDir_None)
7111*61046927SAndroid Build Coastguard Worker             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.
7112*61046927SAndroid Build Coastguard Worker         return pos;
7113*61046927SAndroid Build Coastguard Worker     }
7114*61046927SAndroid Build Coastguard Worker     IM_ASSERT(0);
7115*61046927SAndroid Build Coastguard Worker     return window->Pos;
7116*61046927SAndroid Build Coastguard Worker }
7117*61046927SAndroid Build Coastguard Worker 
7118*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
7119*61046927SAndroid Build Coastguard Worker // [SECTION] VIEWPORTS, PLATFORM WINDOWS
7120*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
7121*61046927SAndroid Build Coastguard Worker 
7122*61046927SAndroid Build Coastguard Worker // (this section is filled in the 'viewport' and 'docking' branches)
7123*61046927SAndroid Build Coastguard Worker 
7124*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
7125*61046927SAndroid Build Coastguard Worker // [SECTION] KEYBOARD/GAMEPAD NAVIGATION
7126*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
7127*61046927SAndroid Build Coastguard Worker 
ImGetDirQuadrantFromDelta(float dx,float dy)7128*61046927SAndroid Build Coastguard Worker ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
7129*61046927SAndroid Build Coastguard Worker {
7130*61046927SAndroid Build Coastguard Worker     if (ImFabs(dx) > ImFabs(dy))
7131*61046927SAndroid Build Coastguard Worker         return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
7132*61046927SAndroid Build Coastguard Worker     return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
7133*61046927SAndroid Build Coastguard Worker }
7134*61046927SAndroid Build Coastguard Worker 
NavScoreItemDistInterval(float a0,float a1,float b0,float b1)7135*61046927SAndroid Build Coastguard Worker static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
7136*61046927SAndroid Build Coastguard Worker {
7137*61046927SAndroid Build Coastguard Worker     if (a1 < b0)
7138*61046927SAndroid Build Coastguard Worker         return a1 - b0;
7139*61046927SAndroid Build Coastguard Worker     if (b1 < a0)
7140*61046927SAndroid Build Coastguard Worker         return a0 - b1;
7141*61046927SAndroid Build Coastguard Worker     return 0.0f;
7142*61046927SAndroid Build Coastguard Worker }
7143*61046927SAndroid Build Coastguard Worker 
NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir,ImRect & r,const ImRect & clip_rect)7144*61046927SAndroid Build Coastguard Worker static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect)
7145*61046927SAndroid Build Coastguard Worker {
7146*61046927SAndroid Build Coastguard Worker     if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
7147*61046927SAndroid Build Coastguard Worker     {
7148*61046927SAndroid Build Coastguard Worker         r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y);
7149*61046927SAndroid Build Coastguard Worker         r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y);
7150*61046927SAndroid Build Coastguard Worker     }
7151*61046927SAndroid Build Coastguard Worker     else
7152*61046927SAndroid Build Coastguard Worker     {
7153*61046927SAndroid Build Coastguard Worker         r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x);
7154*61046927SAndroid Build Coastguard Worker         r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x);
7155*61046927SAndroid Build Coastguard Worker     }
7156*61046927SAndroid Build Coastguard Worker }
7157*61046927SAndroid Build Coastguard Worker 
7158*61046927SAndroid Build Coastguard Worker // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057
NavScoreItem(ImGuiNavMoveResult * result,ImRect cand)7159*61046927SAndroid Build Coastguard Worker static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
7160*61046927SAndroid Build Coastguard Worker {
7161*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7162*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
7163*61046927SAndroid Build Coastguard Worker     if (g.NavLayer != window->DC.NavLayerCurrent)
7164*61046927SAndroid Build Coastguard Worker         return false;
7165*61046927SAndroid Build Coastguard Worker 
7166*61046927SAndroid Build Coastguard Worker     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)
7167*61046927SAndroid Build Coastguard Worker     g.NavScoringCount++;
7168*61046927SAndroid Build Coastguard Worker 
7169*61046927SAndroid Build Coastguard Worker     // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
7170*61046927SAndroid Build Coastguard Worker     if (window->ParentWindow == g.NavWindow)
7171*61046927SAndroid Build Coastguard Worker     {
7172*61046927SAndroid Build Coastguard Worker         IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
7173*61046927SAndroid Build Coastguard Worker         if (!window->ClipRect.Contains(cand))
7174*61046927SAndroid Build Coastguard Worker             return false;
7175*61046927SAndroid Build Coastguard Worker         cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window
7176*61046927SAndroid Build Coastguard Worker     }
7177*61046927SAndroid Build Coastguard Worker 
7178*61046927SAndroid Build Coastguard Worker     // 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)
7179*61046927SAndroid Build Coastguard Worker     // For example, this ensure that items in one column are not reached when moving vertically from items in another column.
7180*61046927SAndroid Build Coastguard Worker     NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect);
7181*61046927SAndroid Build Coastguard Worker 
7182*61046927SAndroid Build Coastguard Worker     // Compute distance between boxes
7183*61046927SAndroid Build Coastguard Worker     // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
7184*61046927SAndroid Build Coastguard Worker     float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
7185*61046927SAndroid Build Coastguard Worker     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
7186*61046927SAndroid Build Coastguard Worker     if (dby != 0.0f && dbx != 0.0f)
7187*61046927SAndroid Build Coastguard Worker        dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
7188*61046927SAndroid Build Coastguard Worker     float dist_box = ImFabs(dbx) + ImFabs(dby);
7189*61046927SAndroid Build Coastguard Worker 
7190*61046927SAndroid Build Coastguard Worker     // 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)
7191*61046927SAndroid Build Coastguard Worker     float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
7192*61046927SAndroid Build Coastguard Worker     float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
7193*61046927SAndroid Build Coastguard Worker     float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee)
7194*61046927SAndroid Build Coastguard Worker 
7195*61046927SAndroid Build Coastguard Worker     // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
7196*61046927SAndroid Build Coastguard Worker     ImGuiDir quadrant;
7197*61046927SAndroid Build Coastguard Worker     float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
7198*61046927SAndroid Build Coastguard Worker     if (dbx != 0.0f || dby != 0.0f)
7199*61046927SAndroid Build Coastguard Worker     {
7200*61046927SAndroid Build Coastguard Worker         // For non-overlapping boxes, use distance between boxes
7201*61046927SAndroid Build Coastguard Worker         dax = dbx;
7202*61046927SAndroid Build Coastguard Worker         day = dby;
7203*61046927SAndroid Build Coastguard Worker         dist_axial = dist_box;
7204*61046927SAndroid Build Coastguard Worker         quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
7205*61046927SAndroid Build Coastguard Worker     }
7206*61046927SAndroid Build Coastguard Worker     else if (dcx != 0.0f || dcy != 0.0f)
7207*61046927SAndroid Build Coastguard Worker     {
7208*61046927SAndroid Build Coastguard Worker         // For overlapping boxes with different centers, use distance between centers
7209*61046927SAndroid Build Coastguard Worker         dax = dcx;
7210*61046927SAndroid Build Coastguard Worker         day = dcy;
7211*61046927SAndroid Build Coastguard Worker         dist_axial = dist_center;
7212*61046927SAndroid Build Coastguard Worker         quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
7213*61046927SAndroid Build Coastguard Worker     }
7214*61046927SAndroid Build Coastguard Worker     else
7215*61046927SAndroid Build Coastguard Worker     {
7216*61046927SAndroid Build Coastguard Worker         // 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)
7217*61046927SAndroid Build Coastguard Worker         quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
7218*61046927SAndroid Build Coastguard Worker     }
7219*61046927SAndroid Build Coastguard Worker 
7220*61046927SAndroid Build Coastguard Worker #if IMGUI_DEBUG_NAV_SCORING
7221*61046927SAndroid Build Coastguard Worker     char buf[128];
7222*61046927SAndroid Build Coastguard Worker     if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max))
7223*61046927SAndroid Build Coastguard Worker     {
7224*61046927SAndroid Build Coastguard Worker         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]);
7225*61046927SAndroid Build Coastguard Worker         ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7226*61046927SAndroid Build Coastguard Worker         draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100));
7227*61046927SAndroid Build Coastguard Worker         draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200));
7228*61046927SAndroid Build Coastguard Worker         draw_list->AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150));
7229*61046927SAndroid Build Coastguard Worker         draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf);
7230*61046927SAndroid Build Coastguard Worker     }
7231*61046927SAndroid Build Coastguard Worker     else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
7232*61046927SAndroid Build Coastguard Worker     {
7233*61046927SAndroid Build Coastguard Worker         if (ImGui::IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; }
7234*61046927SAndroid Build Coastguard Worker         if (quadrant == g.NavMoveDir)
7235*61046927SAndroid Build Coastguard Worker         {
7236*61046927SAndroid Build Coastguard Worker             ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
7237*61046927SAndroid Build Coastguard Worker             ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7238*61046927SAndroid Build Coastguard Worker             draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200));
7239*61046927SAndroid Build Coastguard Worker             draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf);
7240*61046927SAndroid Build Coastguard Worker         }
7241*61046927SAndroid Build Coastguard Worker     }
7242*61046927SAndroid Build Coastguard Worker  #endif
7243*61046927SAndroid Build Coastguard Worker 
7244*61046927SAndroid Build Coastguard Worker     // Is it in the quadrant we're interesting in moving to?
7245*61046927SAndroid Build Coastguard Worker     bool new_best = false;
7246*61046927SAndroid Build Coastguard Worker     if (quadrant == g.NavMoveDir)
7247*61046927SAndroid Build Coastguard Worker     {
7248*61046927SAndroid Build Coastguard Worker         // Does it beat the current best candidate?
7249*61046927SAndroid Build Coastguard Worker         if (dist_box < result->DistBox)
7250*61046927SAndroid Build Coastguard Worker         {
7251*61046927SAndroid Build Coastguard Worker             result->DistBox = dist_box;
7252*61046927SAndroid Build Coastguard Worker             result->DistCenter = dist_center;
7253*61046927SAndroid Build Coastguard Worker             return true;
7254*61046927SAndroid Build Coastguard Worker         }
7255*61046927SAndroid Build Coastguard Worker         if (dist_box == result->DistBox)
7256*61046927SAndroid Build Coastguard Worker         {
7257*61046927SAndroid Build Coastguard Worker             // Try using distance between center points to break ties
7258*61046927SAndroid Build Coastguard Worker             if (dist_center < result->DistCenter)
7259*61046927SAndroid Build Coastguard Worker             {
7260*61046927SAndroid Build Coastguard Worker                 result->DistCenter = dist_center;
7261*61046927SAndroid Build Coastguard Worker                 new_best = true;
7262*61046927SAndroid Build Coastguard Worker             }
7263*61046927SAndroid Build Coastguard Worker             else if (dist_center == result->DistCenter)
7264*61046927SAndroid Build Coastguard Worker             {
7265*61046927SAndroid Build Coastguard Worker                 // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
7266*61046927SAndroid Build Coastguard Worker                 // (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),
7267*61046927SAndroid Build Coastguard Worker                 // 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.
7268*61046927SAndroid Build Coastguard Worker                 if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
7269*61046927SAndroid Build Coastguard Worker                     new_best = true;
7270*61046927SAndroid Build Coastguard Worker             }
7271*61046927SAndroid Build Coastguard Worker         }
7272*61046927SAndroid Build Coastguard Worker     }
7273*61046927SAndroid Build Coastguard Worker 
7274*61046927SAndroid Build Coastguard Worker     // 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
7275*61046927SAndroid Build Coastguard Worker     // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
7276*61046927SAndroid Build Coastguard Worker     // 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.
7277*61046927SAndroid Build Coastguard Worker     // 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.
7278*61046927SAndroid Build Coastguard Worker     // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
7279*61046927SAndroid Build Coastguard Worker     if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)  // Check axial match
7280*61046927SAndroid Build Coastguard Worker         if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
7281*61046927SAndroid Build Coastguard Worker             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))
7282*61046927SAndroid Build Coastguard Worker             {
7283*61046927SAndroid Build Coastguard Worker                 result->DistAxial = dist_axial;
7284*61046927SAndroid Build Coastguard Worker                 new_best = true;
7285*61046927SAndroid Build Coastguard Worker             }
7286*61046927SAndroid Build Coastguard Worker 
7287*61046927SAndroid Build Coastguard Worker     return new_best;
7288*61046927SAndroid Build Coastguard Worker }
7289*61046927SAndroid Build Coastguard Worker 
7290*61046927SAndroid Build Coastguard Worker // We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
NavProcessItem(ImGuiWindow * window,const ImRect & nav_bb,const ImGuiID id)7291*61046927SAndroid Build Coastguard Worker static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
7292*61046927SAndroid Build Coastguard Worker {
7293*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7294*61046927SAndroid Build Coastguard Worker     //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.
7295*61046927SAndroid Build Coastguard Worker     //    return;
7296*61046927SAndroid Build Coastguard Worker 
7297*61046927SAndroid Build Coastguard Worker     const ImGuiItemFlags item_flags = window->DC.ItemFlags;
7298*61046927SAndroid Build Coastguard Worker     const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
7299*61046927SAndroid Build Coastguard Worker 
7300*61046927SAndroid Build Coastguard Worker     // Process Init Request
7301*61046927SAndroid Build Coastguard Worker     if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
7302*61046927SAndroid Build Coastguard Worker     {
7303*61046927SAndroid Build Coastguard Worker         // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
7304*61046927SAndroid Build Coastguard Worker         if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0)
7305*61046927SAndroid Build Coastguard Worker         {
7306*61046927SAndroid Build Coastguard Worker             g.NavInitResultId = id;
7307*61046927SAndroid Build Coastguard Worker             g.NavInitResultRectRel = nav_bb_rel;
7308*61046927SAndroid Build Coastguard Worker         }
7309*61046927SAndroid Build Coastguard Worker         if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus))
7310*61046927SAndroid Build Coastguard Worker         {
7311*61046927SAndroid Build Coastguard Worker             g.NavInitRequest = false; // Found a match, clear request
7312*61046927SAndroid Build Coastguard Worker             NavUpdateAnyRequestFlag();
7313*61046927SAndroid Build Coastguard Worker         }
7314*61046927SAndroid Build Coastguard Worker     }
7315*61046927SAndroid Build Coastguard Worker 
7316*61046927SAndroid Build Coastguard Worker     // Process Move Request (scoring for navigation)
7317*61046927SAndroid Build Coastguard Worker     // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
7318*61046927SAndroid Build Coastguard Worker     if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & ImGuiItemFlags_NoNav))
7319*61046927SAndroid Build Coastguard Worker     {
7320*61046927SAndroid Build Coastguard Worker         ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
7321*61046927SAndroid Build Coastguard Worker #if IMGUI_DEBUG_NAV_SCORING
7322*61046927SAndroid Build Coastguard Worker         // [DEBUG] Score all items in NavWindow at all times
7323*61046927SAndroid Build Coastguard Worker         if (!g.NavMoveRequest)
7324*61046927SAndroid Build Coastguard Worker             g.NavMoveDir = g.NavMoveDirLast;
7325*61046927SAndroid Build Coastguard Worker         bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest;
7326*61046927SAndroid Build Coastguard Worker #else
7327*61046927SAndroid Build Coastguard Worker         bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb);
7328*61046927SAndroid Build Coastguard Worker #endif
7329*61046927SAndroid Build Coastguard Worker         if (new_best)
7330*61046927SAndroid Build Coastguard Worker         {
7331*61046927SAndroid Build Coastguard Worker             result->ID = id;
7332*61046927SAndroid Build Coastguard Worker             result->SelectScopeId = g.MultiSelectScopeId;
7333*61046927SAndroid Build Coastguard Worker             result->Window = window;
7334*61046927SAndroid Build Coastguard Worker             result->RectRel = nav_bb_rel;
7335*61046927SAndroid Build Coastguard Worker         }
7336*61046927SAndroid Build Coastguard Worker 
7337*61046927SAndroid Build Coastguard Worker         const float VISIBLE_RATIO = 0.70f;
7338*61046927SAndroid Build Coastguard Worker         if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
7339*61046927SAndroid Build Coastguard Worker             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)
7340*61046927SAndroid Build Coastguard Worker                 if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb))
7341*61046927SAndroid Build Coastguard Worker                 {
7342*61046927SAndroid Build Coastguard Worker                     result = &g.NavMoveResultLocalVisibleSet;
7343*61046927SAndroid Build Coastguard Worker                     result->ID = id;
7344*61046927SAndroid Build Coastguard Worker                     result->SelectScopeId = g.MultiSelectScopeId;
7345*61046927SAndroid Build Coastguard Worker                     result->Window = window;
7346*61046927SAndroid Build Coastguard Worker                     result->RectRel = nav_bb_rel;
7347*61046927SAndroid Build Coastguard Worker                 }
7348*61046927SAndroid Build Coastguard Worker     }
7349*61046927SAndroid Build Coastguard Worker 
7350*61046927SAndroid Build Coastguard Worker     // Update window-relative bounding box of navigated item
7351*61046927SAndroid Build Coastguard Worker     if (g.NavId == id)
7352*61046927SAndroid Build Coastguard Worker     {
7353*61046927SAndroid Build Coastguard Worker         g.NavWindow = window;                                           // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
7354*61046927SAndroid Build Coastguard Worker         g.NavLayer = window->DC.NavLayerCurrent;
7355*61046927SAndroid Build Coastguard Worker         g.NavIdIsAlive = true;
7356*61046927SAndroid Build Coastguard Worker         g.NavIdTabCounter = window->FocusIdxTabCounter;
7357*61046927SAndroid Build Coastguard Worker         window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel;    // Store item bounding box (relative to window position)
7358*61046927SAndroid Build Coastguard Worker     }
7359*61046927SAndroid Build Coastguard Worker }
7360*61046927SAndroid Build Coastguard Worker 
NavMoveRequestButNoResultYet()7361*61046927SAndroid Build Coastguard Worker bool ImGui::NavMoveRequestButNoResultYet()
7362*61046927SAndroid Build Coastguard Worker {
7363*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7364*61046927SAndroid Build Coastguard Worker     return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
7365*61046927SAndroid Build Coastguard Worker }
7366*61046927SAndroid Build Coastguard Worker 
NavMoveRequestCancel()7367*61046927SAndroid Build Coastguard Worker void ImGui::NavMoveRequestCancel()
7368*61046927SAndroid Build Coastguard Worker {
7369*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7370*61046927SAndroid Build Coastguard Worker     g.NavMoveRequest = false;
7371*61046927SAndroid Build Coastguard Worker     NavUpdateAnyRequestFlag();
7372*61046927SAndroid Build Coastguard Worker }
7373*61046927SAndroid Build Coastguard Worker 
NavMoveRequestForward(ImGuiDir move_dir,ImGuiDir clip_dir,const ImRect & bb_rel,ImGuiNavMoveFlags move_flags)7374*61046927SAndroid Build Coastguard Worker void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags)
7375*61046927SAndroid Build Coastguard Worker {
7376*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7377*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
7378*61046927SAndroid Build Coastguard Worker     ImGui::NavMoveRequestCancel();
7379*61046927SAndroid Build Coastguard Worker     g.NavMoveDir = move_dir;
7380*61046927SAndroid Build Coastguard Worker     g.NavMoveClipDir = clip_dir;
7381*61046927SAndroid Build Coastguard Worker     g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
7382*61046927SAndroid Build Coastguard Worker     g.NavMoveRequestFlags = move_flags;
7383*61046927SAndroid Build Coastguard Worker     g.NavWindow->NavRectRel[g.NavLayer] = bb_rel;
7384*61046927SAndroid Build Coastguard Worker }
7385*61046927SAndroid Build Coastguard Worker 
NavMoveRequestTryWrapping(ImGuiWindow * window,ImGuiNavMoveFlags move_flags)7386*61046927SAndroid Build Coastguard Worker void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
7387*61046927SAndroid Build Coastguard Worker {
7388*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7389*61046927SAndroid Build Coastguard Worker     if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0)
7390*61046927SAndroid Build Coastguard Worker         return;
7391*61046927SAndroid Build Coastguard Worker     IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
7392*61046927SAndroid Build Coastguard Worker     ImRect bb_rel = window->NavRectRel[0];
7393*61046927SAndroid Build Coastguard Worker 
7394*61046927SAndroid Build Coastguard Worker     ImGuiDir clip_dir = g.NavMoveDir;
7395*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
7396*61046927SAndroid Build Coastguard Worker     {
7397*61046927SAndroid Build Coastguard Worker         bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
7398*61046927SAndroid Build Coastguard Worker         if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
7399*61046927SAndroid Build Coastguard Worker         NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7400*61046927SAndroid Build Coastguard Worker     }
7401*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
7402*61046927SAndroid Build Coastguard Worker     {
7403*61046927SAndroid Build Coastguard Worker         bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
7404*61046927SAndroid Build Coastguard Worker         if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
7405*61046927SAndroid Build Coastguard Worker         NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7406*61046927SAndroid Build Coastguard Worker     }
7407*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
7408*61046927SAndroid Build Coastguard Worker     {
7409*61046927SAndroid Build Coastguard Worker         bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
7410*61046927SAndroid Build Coastguard Worker         if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
7411*61046927SAndroid Build Coastguard Worker         NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7412*61046927SAndroid Build Coastguard Worker     }
7413*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
7414*61046927SAndroid Build Coastguard Worker     {
7415*61046927SAndroid Build Coastguard Worker         bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
7416*61046927SAndroid Build Coastguard Worker         if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
7417*61046927SAndroid Build Coastguard Worker         NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
7418*61046927SAndroid Build Coastguard Worker     }
7419*61046927SAndroid Build Coastguard Worker }
7420*61046927SAndroid Build Coastguard Worker 
NavSaveLastChildNavWindow(ImGuiWindow * nav_window)7421*61046927SAndroid Build Coastguard Worker static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window)
7422*61046927SAndroid Build Coastguard Worker {
7423*61046927SAndroid Build Coastguard Worker     ImGuiWindow* parent_window = nav_window;
7424*61046927SAndroid Build Coastguard Worker     while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
7425*61046927SAndroid Build Coastguard Worker         parent_window = parent_window->ParentWindow;
7426*61046927SAndroid Build Coastguard Worker     if (parent_window && parent_window != nav_window)
7427*61046927SAndroid Build Coastguard Worker         parent_window->NavLastChildNavWindow = nav_window;
7428*61046927SAndroid Build Coastguard Worker }
7429*61046927SAndroid Build Coastguard Worker 
7430*61046927SAndroid Build Coastguard Worker // Call when we are expected to land on Layer 0 after FocusWindow()
NavRestoreLastChildNavWindow(ImGuiWindow * window)7431*61046927SAndroid Build Coastguard Worker static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
7432*61046927SAndroid Build Coastguard Worker {
7433*61046927SAndroid Build Coastguard Worker     return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
7434*61046927SAndroid Build Coastguard Worker }
7435*61046927SAndroid Build Coastguard Worker 
NavRestoreLayer(ImGuiNavLayer layer)7436*61046927SAndroid Build Coastguard Worker static void NavRestoreLayer(ImGuiNavLayer layer)
7437*61046927SAndroid Build Coastguard Worker {
7438*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7439*61046927SAndroid Build Coastguard Worker     g.NavLayer = layer;
7440*61046927SAndroid Build Coastguard Worker     if (layer == 0)
7441*61046927SAndroid Build Coastguard Worker         g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow);
7442*61046927SAndroid Build Coastguard Worker     if (layer == 0 && g.NavWindow->NavLastIds[0] != 0)
7443*61046927SAndroid Build Coastguard Worker         ImGui::SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]);
7444*61046927SAndroid Build Coastguard Worker     else
7445*61046927SAndroid Build Coastguard Worker         ImGui::NavInitWindow(g.NavWindow, true);
7446*61046927SAndroid Build Coastguard Worker }
7447*61046927SAndroid Build Coastguard Worker 
NavUpdateAnyRequestFlag()7448*61046927SAndroid Build Coastguard Worker static inline void ImGui::NavUpdateAnyRequestFlag()
7449*61046927SAndroid Build Coastguard Worker {
7450*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7451*61046927SAndroid Build Coastguard Worker     g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
7452*61046927SAndroid Build Coastguard Worker     if (g.NavAnyRequest)
7453*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavWindow != NULL);
7454*61046927SAndroid Build Coastguard Worker }
7455*61046927SAndroid Build Coastguard Worker 
7456*61046927SAndroid Build Coastguard Worker // This needs to be called before we submit any widget (aka in or before Begin)
NavInitWindow(ImGuiWindow * window,bool force_reinit)7457*61046927SAndroid Build Coastguard Worker void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
7458*61046927SAndroid Build Coastguard Worker {
7459*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7460*61046927SAndroid Build Coastguard Worker     IM_ASSERT(window == g.NavWindow);
7461*61046927SAndroid Build Coastguard Worker     bool init_for_nav = false;
7462*61046927SAndroid Build Coastguard Worker     if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
7463*61046927SAndroid Build Coastguard Worker         if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
7464*61046927SAndroid Build Coastguard Worker             init_for_nav = true;
7465*61046927SAndroid Build Coastguard Worker     if (init_for_nav)
7466*61046927SAndroid Build Coastguard Worker     {
7467*61046927SAndroid Build Coastguard Worker         SetNavID(0, g.NavLayer);
7468*61046927SAndroid Build Coastguard Worker         g.NavInitRequest = true;
7469*61046927SAndroid Build Coastguard Worker         g.NavInitRequestFromMove = false;
7470*61046927SAndroid Build Coastguard Worker         g.NavInitResultId = 0;
7471*61046927SAndroid Build Coastguard Worker         g.NavInitResultRectRel = ImRect();
7472*61046927SAndroid Build Coastguard Worker         NavUpdateAnyRequestFlag();
7473*61046927SAndroid Build Coastguard Worker     }
7474*61046927SAndroid Build Coastguard Worker     else
7475*61046927SAndroid Build Coastguard Worker     {
7476*61046927SAndroid Build Coastguard Worker         g.NavId = window->NavLastIds[0];
7477*61046927SAndroid Build Coastguard Worker     }
7478*61046927SAndroid Build Coastguard Worker }
7479*61046927SAndroid Build Coastguard Worker 
NavCalcPreferredRefPos()7480*61046927SAndroid Build Coastguard Worker static ImVec2 ImGui::NavCalcPreferredRefPos()
7481*61046927SAndroid Build Coastguard Worker {
7482*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7483*61046927SAndroid Build Coastguard Worker     if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
7484*61046927SAndroid Build Coastguard Worker     {
7485*61046927SAndroid Build Coastguard Worker         // Mouse (we need a fallback in case the mouse becomes invalid after being used)
7486*61046927SAndroid Build Coastguard Worker         if (IsMousePosValid(&g.IO.MousePos))
7487*61046927SAndroid Build Coastguard Worker             return g.IO.MousePos;
7488*61046927SAndroid Build Coastguard Worker         return g.LastValidMousePos;
7489*61046927SAndroid Build Coastguard Worker     }
7490*61046927SAndroid Build Coastguard Worker     else
7491*61046927SAndroid Build Coastguard Worker     {
7492*61046927SAndroid Build Coastguard Worker         // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
7493*61046927SAndroid Build Coastguard Worker         const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
7494*61046927SAndroid Build Coastguard Worker         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()));
7495*61046927SAndroid Build Coastguard Worker         ImRect visible_rect = GetViewportRect();
7496*61046927SAndroid Build Coastguard Worker         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.
7497*61046927SAndroid Build Coastguard Worker     }
7498*61046927SAndroid Build Coastguard Worker }
7499*61046927SAndroid Build Coastguard Worker 
GetNavInputAmount(ImGuiNavInput n,ImGuiInputReadMode mode)7500*61046927SAndroid Build Coastguard Worker float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
7501*61046927SAndroid Build Coastguard Worker {
7502*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7503*61046927SAndroid Build Coastguard Worker     if (mode == ImGuiInputReadMode_Down)
7504*61046927SAndroid Build Coastguard Worker         return g.IO.NavInputs[n];                         // Instant, read analog input (0.0f..1.0f, as provided by user)
7505*61046927SAndroid Build Coastguard Worker 
7506*61046927SAndroid Build Coastguard Worker     const float t = g.IO.NavInputsDownDuration[n];
7507*61046927SAndroid Build Coastguard Worker     if (t < 0.0f && mode == ImGuiInputReadMode_Released)  // Return 1.0f when just released, no repeat, ignore analog input.
7508*61046927SAndroid Build Coastguard Worker         return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
7509*61046927SAndroid Build Coastguard Worker     if (t < 0.0f)
7510*61046927SAndroid Build Coastguard Worker         return 0.0f;
7511*61046927SAndroid Build Coastguard Worker     if (mode == ImGuiInputReadMode_Pressed)               // Return 1.0f when just pressed, no repeat, ignore analog input.
7512*61046927SAndroid Build Coastguard Worker         return (t == 0.0f) ? 1.0f : 0.0f;
7513*61046927SAndroid Build Coastguard Worker     if (mode == ImGuiInputReadMode_Repeat)
7514*61046927SAndroid Build Coastguard Worker         return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f);
7515*61046927SAndroid Build Coastguard Worker     if (mode == ImGuiInputReadMode_RepeatSlow)
7516*61046927SAndroid Build Coastguard Worker         return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f);
7517*61046927SAndroid Build Coastguard Worker     if (mode == ImGuiInputReadMode_RepeatFast)
7518*61046927SAndroid Build Coastguard Worker         return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f);
7519*61046927SAndroid Build Coastguard Worker     return 0.0f;
7520*61046927SAndroid Build Coastguard Worker }
7521*61046927SAndroid Build Coastguard Worker 
GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources,ImGuiInputReadMode mode,float slow_factor,float fast_factor)7522*61046927SAndroid Build Coastguard Worker ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor)
7523*61046927SAndroid Build Coastguard Worker {
7524*61046927SAndroid Build Coastguard Worker     ImVec2 delta(0.0f, 0.0f);
7525*61046927SAndroid Build Coastguard Worker     if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
7526*61046927SAndroid Build Coastguard Worker         delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode)   - GetNavInputAmount(ImGuiNavInput_KeyLeft_,   mode), GetNavInputAmount(ImGuiNavInput_KeyDown_,   mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_,   mode));
7527*61046927SAndroid Build Coastguard Worker     if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
7528*61046927SAndroid Build Coastguard Worker         delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode)   - GetNavInputAmount(ImGuiNavInput_DpadLeft,   mode), GetNavInputAmount(ImGuiNavInput_DpadDown,   mode) - GetNavInputAmount(ImGuiNavInput_DpadUp,   mode));
7529*61046927SAndroid Build Coastguard Worker     if (dir_sources & ImGuiNavDirSourceFlags_PadLStick)
7530*61046927SAndroid Build Coastguard Worker         delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode));
7531*61046927SAndroid Build Coastguard Worker     if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow))
7532*61046927SAndroid Build Coastguard Worker         delta *= slow_factor;
7533*61046927SAndroid Build Coastguard Worker     if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast))
7534*61046927SAndroid Build Coastguard Worker         delta *= fast_factor;
7535*61046927SAndroid Build Coastguard Worker     return delta;
7536*61046927SAndroid Build Coastguard Worker }
7537*61046927SAndroid Build Coastguard Worker 
7538*61046927SAndroid Build Coastguard Worker // Scroll to keep newly navigated item fully into view
7539*61046927SAndroid Build Coastguard Worker // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
NavScrollToBringItemIntoView(ImGuiWindow * window,const ImRect & item_rect)7540*61046927SAndroid Build Coastguard Worker static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
7541*61046927SAndroid Build Coastguard Worker {
7542*61046927SAndroid Build Coastguard Worker     ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
7543*61046927SAndroid Build Coastguard Worker     //GetOverlayDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
7544*61046927SAndroid Build Coastguard Worker     if (window_rect.Contains(item_rect))
7545*61046927SAndroid Build Coastguard Worker         return;
7546*61046927SAndroid Build Coastguard Worker 
7547*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7548*61046927SAndroid Build Coastguard Worker     if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
7549*61046927SAndroid Build Coastguard Worker     {
7550*61046927SAndroid Build Coastguard Worker         window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x;
7551*61046927SAndroid Build Coastguard Worker         window->ScrollTargetCenterRatio.x = 0.0f;
7552*61046927SAndroid Build Coastguard Worker     }
7553*61046927SAndroid Build Coastguard Worker     else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
7554*61046927SAndroid Build Coastguard Worker     {
7555*61046927SAndroid Build Coastguard Worker         window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x;
7556*61046927SAndroid Build Coastguard Worker         window->ScrollTargetCenterRatio.x = 1.0f;
7557*61046927SAndroid Build Coastguard Worker     }
7558*61046927SAndroid Build Coastguard Worker     if (item_rect.Min.y < window_rect.Min.y)
7559*61046927SAndroid Build Coastguard Worker     {
7560*61046927SAndroid Build Coastguard Worker         window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y;
7561*61046927SAndroid Build Coastguard Worker         window->ScrollTargetCenterRatio.y = 0.0f;
7562*61046927SAndroid Build Coastguard Worker     }
7563*61046927SAndroid Build Coastguard Worker     else if (item_rect.Max.y >= window_rect.Max.y)
7564*61046927SAndroid Build Coastguard Worker     {
7565*61046927SAndroid Build Coastguard Worker         window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y;
7566*61046927SAndroid Build Coastguard Worker         window->ScrollTargetCenterRatio.y = 1.0f;
7567*61046927SAndroid Build Coastguard Worker     }
7568*61046927SAndroid Build Coastguard Worker }
7569*61046927SAndroid Build Coastguard Worker 
NavUpdate()7570*61046927SAndroid Build Coastguard Worker static void ImGui::NavUpdate()
7571*61046927SAndroid Build Coastguard Worker {
7572*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7573*61046927SAndroid Build Coastguard Worker     g.IO.WantSetMousePos = false;
7574*61046927SAndroid Build Coastguard Worker #if 0
7575*61046927SAndroid Build Coastguard Worker     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);
7576*61046927SAndroid Build Coastguard Worker #endif
7577*61046927SAndroid Build Coastguard Worker 
7578*61046927SAndroid Build Coastguard Worker     // Set input source as Gamepad when buttons are pressed before we map Keyboard (some features differs when used with Gamepad vs Keyboard)
7579*61046927SAndroid Build Coastguard Worker     bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
7580*61046927SAndroid Build Coastguard Worker     bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
7581*61046927SAndroid Build Coastguard Worker     if (nav_gamepad_active)
7582*61046927SAndroid Build Coastguard Worker         if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f)
7583*61046927SAndroid Build Coastguard Worker             g.NavInputSource = ImGuiInputSource_NavGamepad;
7584*61046927SAndroid Build Coastguard Worker 
7585*61046927SAndroid Build Coastguard Worker     // Update Keyboard->Nav inputs mapping
7586*61046927SAndroid Build Coastguard Worker     if (nav_keyboard_active)
7587*61046927SAndroid Build Coastguard Worker     {
7588*61046927SAndroid Build Coastguard Worker         #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; }
7589*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_Space,     ImGuiNavInput_Activate );
7590*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_Enter,     ImGuiNavInput_Input    );
7591*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_Escape,    ImGuiNavInput_Cancel   );
7592*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ );
7593*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
7594*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_UpArrow,   ImGuiNavInput_KeyUp_   );
7595*61046927SAndroid Build Coastguard Worker         NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
7596*61046927SAndroid Build Coastguard Worker         if (g.IO.KeyCtrl)   g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
7597*61046927SAndroid Build Coastguard Worker         if (g.IO.KeyShift)  g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
7598*61046927SAndroid Build Coastguard Worker         if (g.IO.KeyAlt)    g.IO.NavInputs[ImGuiNavInput_KeyMenu_]  = 1.0f;
7599*61046927SAndroid Build Coastguard Worker         #undef NAV_MAP_KEY
7600*61046927SAndroid Build Coastguard Worker     }
7601*61046927SAndroid Build Coastguard Worker     memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration));
7602*61046927SAndroid Build Coastguard Worker     for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++)
7603*61046927SAndroid Build Coastguard Worker         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;
7604*61046927SAndroid Build Coastguard Worker 
7605*61046927SAndroid Build Coastguard Worker     // Process navigation init request (select first/default focus)
7606*61046927SAndroid Build Coastguard Worker     if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove))
7607*61046927SAndroid Build Coastguard Worker     {
7608*61046927SAndroid Build Coastguard Worker         // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
7609*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavWindow);
7610*61046927SAndroid Build Coastguard Worker         if (g.NavInitRequestFromMove)
7611*61046927SAndroid Build Coastguard Worker             SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel);
7612*61046927SAndroid Build Coastguard Worker         else
7613*61046927SAndroid Build Coastguard Worker             SetNavID(g.NavInitResultId, g.NavLayer);
7614*61046927SAndroid Build Coastguard Worker         g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel;
7615*61046927SAndroid Build Coastguard Worker     }
7616*61046927SAndroid Build Coastguard Worker     g.NavInitRequest = false;
7617*61046927SAndroid Build Coastguard Worker     g.NavInitRequestFromMove = false;
7618*61046927SAndroid Build Coastguard Worker     g.NavInitResultId = 0;
7619*61046927SAndroid Build Coastguard Worker     g.NavJustMovedToId = 0;
7620*61046927SAndroid Build Coastguard Worker 
7621*61046927SAndroid Build Coastguard Worker     // Process navigation move request
7622*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest)
7623*61046927SAndroid Build Coastguard Worker         NavUpdateMoveResult();
7624*61046927SAndroid Build Coastguard Worker 
7625*61046927SAndroid Build Coastguard Worker     // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame
7626*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive)
7627*61046927SAndroid Build Coastguard Worker     {
7628*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavMoveRequest);
7629*61046927SAndroid Build Coastguard Worker         if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
7630*61046927SAndroid Build Coastguard Worker             g.NavDisableHighlight = false;
7631*61046927SAndroid Build Coastguard Worker         g.NavMoveRequestForward = ImGuiNavForward_None;
7632*61046927SAndroid Build Coastguard Worker     }
7633*61046927SAndroid Build Coastguard Worker 
7634*61046927SAndroid Build Coastguard Worker     // Apply application mouse position movement, after we had a chance to process move request result.
7635*61046927SAndroid Build Coastguard Worker     if (g.NavMousePosDirty && g.NavIdIsAlive)
7636*61046927SAndroid Build Coastguard Worker     {
7637*61046927SAndroid Build Coastguard Worker         // Set mouse position given our knowledge of the navigated item position from last frame
7638*61046927SAndroid Build Coastguard Worker         if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
7639*61046927SAndroid Build Coastguard Worker         {
7640*61046927SAndroid Build Coastguard Worker             if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
7641*61046927SAndroid Build Coastguard Worker             {
7642*61046927SAndroid Build Coastguard Worker                 g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos();
7643*61046927SAndroid Build Coastguard Worker                 g.IO.WantSetMousePos = true;
7644*61046927SAndroid Build Coastguard Worker             }
7645*61046927SAndroid Build Coastguard Worker         }
7646*61046927SAndroid Build Coastguard Worker         g.NavMousePosDirty = false;
7647*61046927SAndroid Build Coastguard Worker     }
7648*61046927SAndroid Build Coastguard Worker     g.NavIdIsAlive = false;
7649*61046927SAndroid Build Coastguard Worker     g.NavJustTabbedId = 0;
7650*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1);
7651*61046927SAndroid Build Coastguard Worker 
7652*61046927SAndroid Build Coastguard Worker     // 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
7653*61046927SAndroid Build Coastguard Worker     if (g.NavWindow)
7654*61046927SAndroid Build Coastguard Worker         NavSaveLastChildNavWindow(g.NavWindow);
7655*61046927SAndroid Build Coastguard Worker     if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0)
7656*61046927SAndroid Build Coastguard Worker         g.NavWindow->NavLastChildNavWindow = NULL;
7657*61046927SAndroid Build Coastguard Worker 
7658*61046927SAndroid Build Coastguard Worker     // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.)
7659*61046927SAndroid Build Coastguard Worker     NavUpdateWindowing();
7660*61046927SAndroid Build Coastguard Worker 
7661*61046927SAndroid Build Coastguard Worker     // Set output flags for user application
7662*61046927SAndroid Build Coastguard Worker     g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
7663*61046927SAndroid Build Coastguard Worker     g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
7664*61046927SAndroid Build Coastguard Worker 
7665*61046927SAndroid Build Coastguard Worker     // Process NavCancel input (to close a popup, get back to parent, clear focus)
7666*61046927SAndroid Build Coastguard Worker     if (IsNavInputPressed(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed))
7667*61046927SAndroid Build Coastguard Worker     {
7668*61046927SAndroid Build Coastguard Worker         if (g.ActiveId != 0)
7669*61046927SAndroid Build Coastguard Worker         {
7670*61046927SAndroid Build Coastguard Worker             if (!(g.ActiveIdBlockNavInputFlags & (1 << ImGuiNavInput_Cancel)))
7671*61046927SAndroid Build Coastguard Worker                 ClearActiveID();
7672*61046927SAndroid Build Coastguard Worker         }
7673*61046927SAndroid Build Coastguard Worker         else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
7674*61046927SAndroid Build Coastguard Worker         {
7675*61046927SAndroid Build Coastguard Worker             // Exit child window
7676*61046927SAndroid Build Coastguard Worker             ImGuiWindow* child_window = g.NavWindow;
7677*61046927SAndroid Build Coastguard Worker             ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
7678*61046927SAndroid Build Coastguard Worker             IM_ASSERT(child_window->ChildId != 0);
7679*61046927SAndroid Build Coastguard Worker             FocusWindow(parent_window);
7680*61046927SAndroid Build Coastguard Worker             SetNavID(child_window->ChildId, 0);
7681*61046927SAndroid Build Coastguard Worker             g.NavIdIsAlive = false;
7682*61046927SAndroid Build Coastguard Worker             if (g.NavDisableMouseHover)
7683*61046927SAndroid Build Coastguard Worker                 g.NavMousePosDirty = true;
7684*61046927SAndroid Build Coastguard Worker         }
7685*61046927SAndroid Build Coastguard Worker         else if (g.OpenPopupStack.Size > 0)
7686*61046927SAndroid Build Coastguard Worker         {
7687*61046927SAndroid Build Coastguard Worker             // Close open popup/menu
7688*61046927SAndroid Build Coastguard Worker             if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
7689*61046927SAndroid Build Coastguard Worker                 ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
7690*61046927SAndroid Build Coastguard Worker         }
7691*61046927SAndroid Build Coastguard Worker         else if (g.NavLayer != 0)
7692*61046927SAndroid Build Coastguard Worker         {
7693*61046927SAndroid Build Coastguard Worker             // Leave the "menu" layer
7694*61046927SAndroid Build Coastguard Worker             NavRestoreLayer(ImGuiNavLayer_Main);
7695*61046927SAndroid Build Coastguard Worker         }
7696*61046927SAndroid Build Coastguard Worker         else
7697*61046927SAndroid Build Coastguard Worker         {
7698*61046927SAndroid Build Coastguard Worker             // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
7699*61046927SAndroid Build Coastguard Worker             if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
7700*61046927SAndroid Build Coastguard Worker                 g.NavWindow->NavLastIds[0] = 0;
7701*61046927SAndroid Build Coastguard Worker             g.NavId = 0;
7702*61046927SAndroid Build Coastguard Worker         }
7703*61046927SAndroid Build Coastguard Worker     }
7704*61046927SAndroid Build Coastguard Worker 
7705*61046927SAndroid Build Coastguard Worker     // Process manual activation request
7706*61046927SAndroid Build Coastguard Worker     g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0;
7707*61046927SAndroid Build Coastguard Worker     if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
7708*61046927SAndroid Build Coastguard Worker     {
7709*61046927SAndroid Build Coastguard Worker         bool activate_down = IsNavInputDown(ImGuiNavInput_Activate);
7710*61046927SAndroid Build Coastguard Worker         bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed);
7711*61046927SAndroid Build Coastguard Worker         if (g.ActiveId == 0 && activate_pressed)
7712*61046927SAndroid Build Coastguard Worker             g.NavActivateId = g.NavId;
7713*61046927SAndroid Build Coastguard Worker         if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
7714*61046927SAndroid Build Coastguard Worker             g.NavActivateDownId = g.NavId;
7715*61046927SAndroid Build Coastguard Worker         if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
7716*61046927SAndroid Build Coastguard Worker             g.NavActivatePressedId = g.NavId;
7717*61046927SAndroid Build Coastguard Worker         if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed))
7718*61046927SAndroid Build Coastguard Worker             g.NavInputId = g.NavId;
7719*61046927SAndroid Build Coastguard Worker     }
7720*61046927SAndroid Build Coastguard Worker     if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
7721*61046927SAndroid Build Coastguard Worker         g.NavDisableHighlight = true;
7722*61046927SAndroid Build Coastguard Worker     if (g.NavActivateId != 0)
7723*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
7724*61046927SAndroid Build Coastguard Worker     g.NavMoveRequest = false;
7725*61046927SAndroid Build Coastguard Worker 
7726*61046927SAndroid Build Coastguard Worker     // Process programmatic activation request
7727*61046927SAndroid Build Coastguard Worker     if (g.NavNextActivateId != 0)
7728*61046927SAndroid Build Coastguard Worker         g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId;
7729*61046927SAndroid Build Coastguard Worker     g.NavNextActivateId = 0;
7730*61046927SAndroid Build Coastguard Worker 
7731*61046927SAndroid Build Coastguard Worker     // Initiate directional inputs request
7732*61046927SAndroid Build Coastguard Worker     const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags;
7733*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequestForward == ImGuiNavForward_None)
7734*61046927SAndroid Build Coastguard Worker     {
7735*61046927SAndroid Build Coastguard Worker         g.NavMoveDir = ImGuiDir_None;
7736*61046927SAndroid Build Coastguard Worker         g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
7737*61046927SAndroid Build Coastguard Worker         if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
7738*61046927SAndroid Build Coastguard Worker         {
7739*61046927SAndroid Build Coastguard Worker             if ((allowed_dir_flags & (1<<ImGuiDir_Left))  && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left;
7740*61046927SAndroid Build Coastguard Worker             if ((allowed_dir_flags & (1<<ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Right;
7741*61046927SAndroid Build Coastguard Worker             if ((allowed_dir_flags & (1<<ImGuiDir_Up))    && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp,   ImGuiNavInput_KeyUp_,   ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up;
7742*61046927SAndroid Build Coastguard Worker             if ((allowed_dir_flags & (1<<ImGuiDir_Down))  && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down;
7743*61046927SAndroid Build Coastguard Worker         }
7744*61046927SAndroid Build Coastguard Worker         g.NavMoveClipDir = g.NavMoveDir;
7745*61046927SAndroid Build Coastguard Worker     }
7746*61046927SAndroid Build Coastguard Worker     else
7747*61046927SAndroid Build Coastguard Worker     {
7748*61046927SAndroid Build Coastguard Worker         // 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)
7749*61046927SAndroid Build Coastguard Worker         // (Preserve g.NavMoveRequestFlags, g.NavMoveClipDir which were set by the NavMoveRequestForward() function)
7750*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
7751*61046927SAndroid Build Coastguard Worker         IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_ForwardQueued);
7752*61046927SAndroid Build Coastguard Worker         g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
7753*61046927SAndroid Build Coastguard Worker     }
7754*61046927SAndroid Build Coastguard Worker 
7755*61046927SAndroid Build Coastguard Worker     // Update PageUp/PageDown scroll
7756*61046927SAndroid Build Coastguard Worker     float nav_scoring_rect_offset_y = 0.0f;
7757*61046927SAndroid Build Coastguard Worker     if (nav_keyboard_active)
7758*61046927SAndroid Build Coastguard Worker         nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
7759*61046927SAndroid Build Coastguard Worker 
7760*61046927SAndroid Build Coastguard Worker     // 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
7761*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir != ImGuiDir_None)
7762*61046927SAndroid Build Coastguard Worker     {
7763*61046927SAndroid Build Coastguard Worker         g.NavMoveRequest = true;
7764*61046927SAndroid Build Coastguard Worker         g.NavMoveDirLast = g.NavMoveDir;
7765*61046927SAndroid Build Coastguard Worker     }
7766*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest && g.NavId == 0)
7767*61046927SAndroid Build Coastguard Worker     {
7768*61046927SAndroid Build Coastguard Worker         g.NavInitRequest = g.NavInitRequestFromMove = true;
7769*61046927SAndroid Build Coastguard Worker         g.NavInitResultId = 0;
7770*61046927SAndroid Build Coastguard Worker         g.NavDisableHighlight = false;
7771*61046927SAndroid Build Coastguard Worker     }
7772*61046927SAndroid Build Coastguard Worker     NavUpdateAnyRequestFlag();
7773*61046927SAndroid Build Coastguard Worker 
7774*61046927SAndroid Build Coastguard Worker     // Scrolling
7775*61046927SAndroid Build Coastguard Worker     if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
7776*61046927SAndroid Build Coastguard Worker     {
7777*61046927SAndroid Build Coastguard Worker         // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
7778*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.NavWindow;
7779*61046927SAndroid Build Coastguard Worker         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.
7780*61046927SAndroid Build Coastguard Worker         if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
7781*61046927SAndroid Build Coastguard Worker         {
7782*61046927SAndroid Build Coastguard Worker             if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
7783*61046927SAndroid Build Coastguard Worker                 SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
7784*61046927SAndroid Build Coastguard Worker             if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)
7785*61046927SAndroid Build Coastguard Worker                 SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
7786*61046927SAndroid Build Coastguard Worker         }
7787*61046927SAndroid Build Coastguard Worker 
7788*61046927SAndroid Build Coastguard Worker         // *Normal* Manual scroll with NavScrollXXX keys
7789*61046927SAndroid Build Coastguard Worker         // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
7790*61046927SAndroid Build Coastguard Worker         ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f);
7791*61046927SAndroid Build Coastguard Worker         if (scroll_dir.x != 0.0f && window->ScrollbarX)
7792*61046927SAndroid Build Coastguard Worker         {
7793*61046927SAndroid Build Coastguard Worker             SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
7794*61046927SAndroid Build Coastguard Worker             g.NavMoveFromClampedRefRect = true;
7795*61046927SAndroid Build Coastguard Worker         }
7796*61046927SAndroid Build Coastguard Worker         if (scroll_dir.y != 0.0f)
7797*61046927SAndroid Build Coastguard Worker         {
7798*61046927SAndroid Build Coastguard Worker             SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
7799*61046927SAndroid Build Coastguard Worker             g.NavMoveFromClampedRefRect = true;
7800*61046927SAndroid Build Coastguard Worker         }
7801*61046927SAndroid Build Coastguard Worker     }
7802*61046927SAndroid Build Coastguard Worker 
7803*61046927SAndroid Build Coastguard Worker     // Reset search results
7804*61046927SAndroid Build Coastguard Worker     g.NavMoveResultLocal.Clear();
7805*61046927SAndroid Build Coastguard Worker     g.NavMoveResultLocalVisibleSet.Clear();
7806*61046927SAndroid Build Coastguard Worker     g.NavMoveResultOther.Clear();
7807*61046927SAndroid Build Coastguard Worker 
7808*61046927SAndroid Build Coastguard Worker     // 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
7809*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
7810*61046927SAndroid Build Coastguard Worker     {
7811*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.NavWindow;
7812*61046927SAndroid Build Coastguard Worker         ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
7813*61046927SAndroid Build Coastguard Worker         if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
7814*61046927SAndroid Build Coastguard Worker         {
7815*61046927SAndroid Build Coastguard Worker             float pad = window->CalcFontSize() * 0.5f;
7816*61046927SAndroid Build Coastguard Worker             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
7817*61046927SAndroid Build Coastguard Worker             window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel);
7818*61046927SAndroid Build Coastguard Worker             g.NavId = 0;
7819*61046927SAndroid Build Coastguard Worker         }
7820*61046927SAndroid Build Coastguard Worker         g.NavMoveFromClampedRefRect = false;
7821*61046927SAndroid Build Coastguard Worker     }
7822*61046927SAndroid Build Coastguard Worker 
7823*61046927SAndroid Build Coastguard Worker     // 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)
7824*61046927SAndroid Build Coastguard Worker     ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0);
7825*61046927SAndroid Build Coastguard Worker     g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect();
7826*61046927SAndroid Build Coastguard Worker     g.NavScoringRectScreen.TranslateY(nav_scoring_rect_offset_y);
7827*61046927SAndroid Build Coastguard Worker     g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x);
7828*61046927SAndroid Build Coastguard Worker     g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x;
7829*61046927SAndroid Build Coastguard Worker     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().
7830*61046927SAndroid Build Coastguard Worker     //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG]
7831*61046927SAndroid Build Coastguard Worker     g.NavScoringCount = 0;
7832*61046927SAndroid Build Coastguard Worker #if IMGUI_DEBUG_NAV_RECTS
7833*61046927SAndroid Build Coastguard Worker     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]
7834*61046927SAndroid Build Coastguard Worker     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); }
7835*61046927SAndroid Build Coastguard Worker #endif
7836*61046927SAndroid Build Coastguard Worker }
7837*61046927SAndroid Build Coastguard Worker 
7838*61046927SAndroid Build Coastguard Worker // Apply result from previous frame navigation directional move request
NavUpdateMoveResult()7839*61046927SAndroid Build Coastguard Worker static void ImGui::NavUpdateMoveResult()
7840*61046927SAndroid Build Coastguard Worker {
7841*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7842*61046927SAndroid Build Coastguard Worker     if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
7843*61046927SAndroid Build Coastguard Worker     {
7844*61046927SAndroid Build Coastguard Worker         // 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)
7845*61046927SAndroid Build Coastguard Worker         if (g.NavId != 0)
7846*61046927SAndroid Build Coastguard Worker         {
7847*61046927SAndroid Build Coastguard Worker             g.NavDisableHighlight = false;
7848*61046927SAndroid Build Coastguard Worker             g.NavDisableMouseHover = true;
7849*61046927SAndroid Build Coastguard Worker         }
7850*61046927SAndroid Build Coastguard Worker         return;
7851*61046927SAndroid Build Coastguard Worker     }
7852*61046927SAndroid Build Coastguard Worker 
7853*61046927SAndroid Build Coastguard Worker     // Select which result to use
7854*61046927SAndroid Build Coastguard Worker     ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
7855*61046927SAndroid Build Coastguard Worker 
7856*61046927SAndroid Build Coastguard Worker     // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
7857*61046927SAndroid Build Coastguard Worker     if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
7858*61046927SAndroid Build Coastguard Worker         if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId)
7859*61046927SAndroid Build Coastguard Worker             result = &g.NavMoveResultLocalVisibleSet;
7860*61046927SAndroid Build Coastguard Worker 
7861*61046927SAndroid Build Coastguard Worker     // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
7862*61046927SAndroid Build Coastguard Worker     if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
7863*61046927SAndroid Build Coastguard Worker         if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
7864*61046927SAndroid Build Coastguard Worker             result = &g.NavMoveResultOther;
7865*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavWindow && result->Window);
7866*61046927SAndroid Build Coastguard Worker 
7867*61046927SAndroid Build Coastguard Worker     // Scroll to keep newly navigated item fully into view.
7868*61046927SAndroid Build Coastguard Worker     if (g.NavLayer == 0)
7869*61046927SAndroid Build Coastguard Worker     {
7870*61046927SAndroid Build Coastguard Worker         ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
7871*61046927SAndroid Build Coastguard Worker         NavScrollToBringItemIntoView(result->Window, rect_abs);
7872*61046927SAndroid Build Coastguard Worker 
7873*61046927SAndroid Build Coastguard Worker         // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate()
7874*61046927SAndroid Build Coastguard Worker         ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false);
7875*61046927SAndroid Build Coastguard Worker         ImVec2 delta_scroll = result->Window->Scroll - next_scroll;
7876*61046927SAndroid Build Coastguard Worker         result->RectRel.Translate(delta_scroll);
7877*61046927SAndroid Build Coastguard Worker 
7878*61046927SAndroid Build Coastguard Worker         // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
7879*61046927SAndroid Build Coastguard Worker         if (result->Window->Flags & ImGuiWindowFlags_ChildWindow)
7880*61046927SAndroid Build Coastguard Worker             NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll));
7881*61046927SAndroid Build Coastguard Worker     }
7882*61046927SAndroid Build Coastguard Worker 
7883*61046927SAndroid Build Coastguard Worker     ClearActiveID();
7884*61046927SAndroid Build Coastguard Worker     g.NavWindow = result->Window;
7885*61046927SAndroid Build Coastguard Worker     if (g.NavId != result->ID)
7886*61046927SAndroid Build Coastguard Worker     {
7887*61046927SAndroid Build Coastguard Worker         // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
7888*61046927SAndroid Build Coastguard Worker         g.NavJustMovedToId = result->ID;
7889*61046927SAndroid Build Coastguard Worker         g.NavJustMovedToSelectScopeId = result->SelectScopeId;
7890*61046927SAndroid Build Coastguard Worker     }
7891*61046927SAndroid Build Coastguard Worker     SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel);
7892*61046927SAndroid Build Coastguard Worker     g.NavMoveFromClampedRefRect = false;
7893*61046927SAndroid Build Coastguard Worker }
7894*61046927SAndroid Build Coastguard Worker 
NavUpdatePageUpPageDown(int allowed_dir_flags)7895*61046927SAndroid Build Coastguard Worker static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
7896*61046927SAndroid Build Coastguard Worker {
7897*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7898*61046927SAndroid Build Coastguard Worker     if (g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0)
7899*61046927SAndroid Build Coastguard Worker     {
7900*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.NavWindow;
7901*61046927SAndroid Build Coastguard Worker         bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
7902*61046927SAndroid Build Coastguard Worker         bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
7903*61046927SAndroid Build Coastguard Worker         if (page_up_held != page_down_held) // If either (not both) are pressed
7904*61046927SAndroid Build Coastguard Worker         {
7905*61046927SAndroid Build Coastguard Worker             if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
7906*61046927SAndroid Build Coastguard Worker             {
7907*61046927SAndroid Build Coastguard Worker                 // Fallback manual-scroll when window has no navigable item
7908*61046927SAndroid Build Coastguard Worker                 if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
7909*61046927SAndroid Build Coastguard Worker                     SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
7910*61046927SAndroid Build Coastguard Worker                 else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
7911*61046927SAndroid Build Coastguard Worker                     SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
7912*61046927SAndroid Build Coastguard Worker             }
7913*61046927SAndroid Build Coastguard Worker             else
7914*61046927SAndroid Build Coastguard Worker             {
7915*61046927SAndroid Build Coastguard Worker                 const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
7916*61046927SAndroid Build Coastguard Worker                 const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
7917*61046927SAndroid Build Coastguard Worker                 float nav_scoring_rect_offset_y = 0.0f;
7918*61046927SAndroid Build Coastguard Worker                 if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
7919*61046927SAndroid Build Coastguard Worker                 {
7920*61046927SAndroid Build Coastguard Worker                     nav_scoring_rect_offset_y = -page_offset_y;
7921*61046927SAndroid Build Coastguard Worker                     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)
7922*61046927SAndroid Build Coastguard Worker                     g.NavMoveClipDir = ImGuiDir_Up;
7923*61046927SAndroid Build Coastguard Worker                     g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
7924*61046927SAndroid Build Coastguard Worker                 }
7925*61046927SAndroid Build Coastguard Worker                 else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
7926*61046927SAndroid Build Coastguard Worker                 {
7927*61046927SAndroid Build Coastguard Worker                     nav_scoring_rect_offset_y = +page_offset_y;
7928*61046927SAndroid Build Coastguard Worker                     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)
7929*61046927SAndroid Build Coastguard Worker                     g.NavMoveClipDir = ImGuiDir_Down;
7930*61046927SAndroid Build Coastguard Worker                     g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
7931*61046927SAndroid Build Coastguard Worker                 }
7932*61046927SAndroid Build Coastguard Worker                 return nav_scoring_rect_offset_y;
7933*61046927SAndroid Build Coastguard Worker             }
7934*61046927SAndroid Build Coastguard Worker         }
7935*61046927SAndroid Build Coastguard Worker     }
7936*61046927SAndroid Build Coastguard Worker     return 0.0f;
7937*61046927SAndroid Build Coastguard Worker }
7938*61046927SAndroid Build Coastguard Worker 
FindWindowFocusIndex(ImGuiWindow * window)7939*61046927SAndroid Build Coastguard Worker static int FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
7940*61046927SAndroid Build Coastguard Worker {
7941*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7942*61046927SAndroid Build Coastguard Worker     for (int i = g.WindowsFocusOrder.Size-1; i >= 0; i--)
7943*61046927SAndroid Build Coastguard Worker         if (g.WindowsFocusOrder[i] == window)
7944*61046927SAndroid Build Coastguard Worker             return i;
7945*61046927SAndroid Build Coastguard Worker     return -1;
7946*61046927SAndroid Build Coastguard Worker }
7947*61046927SAndroid Build Coastguard Worker 
FindWindowNavFocusable(int i_start,int i_stop,int dir)7948*61046927SAndroid Build Coastguard Worker static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
7949*61046927SAndroid Build Coastguard Worker {
7950*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7951*61046927SAndroid Build Coastguard Worker     for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir)
7952*61046927SAndroid Build Coastguard Worker         if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i]))
7953*61046927SAndroid Build Coastguard Worker             return g.WindowsFocusOrder[i];
7954*61046927SAndroid Build Coastguard Worker     return NULL;
7955*61046927SAndroid Build Coastguard Worker }
7956*61046927SAndroid Build Coastguard Worker 
NavUpdateWindowingHighlightWindow(int focus_change_dir)7957*61046927SAndroid Build Coastguard Worker static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
7958*61046927SAndroid Build Coastguard Worker {
7959*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7960*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavWindowingTarget);
7961*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
7962*61046927SAndroid Build Coastguard Worker         return;
7963*61046927SAndroid Build Coastguard Worker 
7964*61046927SAndroid Build Coastguard Worker     const int i_current = FindWindowFocusIndex(g.NavWindowingTarget);
7965*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
7966*61046927SAndroid Build Coastguard Worker     if (!window_target)
7967*61046927SAndroid Build Coastguard Worker         window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
7968*61046927SAndroid Build Coastguard Worker     if (window_target) // Don't reset windowing target if there's a single window in the list
7969*61046927SAndroid Build Coastguard Worker         g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
7970*61046927SAndroid Build Coastguard Worker     g.NavWindowingToggleLayer = false;
7971*61046927SAndroid Build Coastguard Worker }
7972*61046927SAndroid Build Coastguard Worker 
7973*61046927SAndroid Build Coastguard Worker // Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer)
NavUpdateWindowing()7974*61046927SAndroid Build Coastguard Worker static void ImGui::NavUpdateWindowing()
7975*61046927SAndroid Build Coastguard Worker {
7976*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
7977*61046927SAndroid Build Coastguard Worker     ImGuiWindow* apply_focus_window = NULL;
7978*61046927SAndroid Build Coastguard Worker     bool apply_toggle_layer = false;
7979*61046927SAndroid Build Coastguard Worker 
7980*61046927SAndroid Build Coastguard Worker     ImGuiWindow* modal_window = GetFrontMostPopupModal();
7981*61046927SAndroid Build Coastguard Worker     if (modal_window != NULL)
7982*61046927SAndroid Build Coastguard Worker     {
7983*61046927SAndroid Build Coastguard Worker         g.NavWindowingTarget = NULL;
7984*61046927SAndroid Build Coastguard Worker         return;
7985*61046927SAndroid Build Coastguard Worker     }
7986*61046927SAndroid Build Coastguard Worker 
7987*61046927SAndroid Build Coastguard Worker     // Fade out
7988*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
7989*61046927SAndroid Build Coastguard Worker     {
7990*61046927SAndroid Build Coastguard Worker         g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f);
7991*61046927SAndroid Build Coastguard Worker         if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
7992*61046927SAndroid Build Coastguard Worker             g.NavWindowingTargetAnim = NULL;
7993*61046927SAndroid Build Coastguard Worker     }
7994*61046927SAndroid Build Coastguard Worker 
7995*61046927SAndroid Build Coastguard Worker     // Start CTRL-TAB or Square+L/R window selection
7996*61046927SAndroid Build Coastguard Worker     bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
7997*61046927SAndroid Build Coastguard Worker     bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
7998*61046927SAndroid Build Coastguard Worker     if (start_windowing_with_gamepad || start_windowing_with_keyboard)
7999*61046927SAndroid Build Coastguard Worker         if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
8000*61046927SAndroid Build Coastguard Worker         {
8001*61046927SAndroid Build Coastguard Worker             g.NavWindowingTarget = g.NavWindowingTargetAnim = window;
8002*61046927SAndroid Build Coastguard Worker             g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
8003*61046927SAndroid Build Coastguard Worker             g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
8004*61046927SAndroid Build Coastguard Worker             g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
8005*61046927SAndroid Build Coastguard Worker         }
8006*61046927SAndroid Build Coastguard Worker 
8007*61046927SAndroid Build Coastguard Worker     // Gamepad update
8008*61046927SAndroid Build Coastguard Worker     g.NavWindowingTimer += g.IO.DeltaTime;
8009*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad)
8010*61046927SAndroid Build Coastguard Worker     {
8011*61046927SAndroid Build Coastguard Worker         // 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
8012*61046927SAndroid Build Coastguard Worker         g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
8013*61046927SAndroid Build Coastguard Worker 
8014*61046927SAndroid Build Coastguard Worker         // Select window to focus
8015*61046927SAndroid Build Coastguard Worker         const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow);
8016*61046927SAndroid Build Coastguard Worker         if (focus_change_dir != 0)
8017*61046927SAndroid Build Coastguard Worker         {
8018*61046927SAndroid Build Coastguard Worker             NavUpdateWindowingHighlightWindow(focus_change_dir);
8019*61046927SAndroid Build Coastguard Worker             g.NavWindowingHighlightAlpha = 1.0f;
8020*61046927SAndroid Build Coastguard Worker         }
8021*61046927SAndroid Build Coastguard Worker 
8022*61046927SAndroid Build Coastguard Worker         // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most)
8023*61046927SAndroid Build Coastguard Worker         if (!IsNavInputDown(ImGuiNavInput_Menu))
8024*61046927SAndroid Build Coastguard Worker         {
8025*61046927SAndroid Build Coastguard Worker             g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore.
8026*61046927SAndroid Build Coastguard Worker             if (g.NavWindowingToggleLayer && g.NavWindow)
8027*61046927SAndroid Build Coastguard Worker                 apply_toggle_layer = true;
8028*61046927SAndroid Build Coastguard Worker             else if (!g.NavWindowingToggleLayer)
8029*61046927SAndroid Build Coastguard Worker                 apply_focus_window = g.NavWindowingTarget;
8030*61046927SAndroid Build Coastguard Worker             g.NavWindowingTarget = NULL;
8031*61046927SAndroid Build Coastguard Worker         }
8032*61046927SAndroid Build Coastguard Worker     }
8033*61046927SAndroid Build Coastguard Worker 
8034*61046927SAndroid Build Coastguard Worker     // Keyboard: Focus
8035*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard)
8036*61046927SAndroid Build Coastguard Worker     {
8037*61046927SAndroid Build Coastguard Worker         // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
8038*61046927SAndroid Build Coastguard Worker         g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
8039*61046927SAndroid Build Coastguard Worker         if (IsKeyPressedMap(ImGuiKey_Tab, true))
8040*61046927SAndroid Build Coastguard Worker             NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1);
8041*61046927SAndroid Build Coastguard Worker         if (!g.IO.KeyCtrl)
8042*61046927SAndroid Build Coastguard Worker             apply_focus_window = g.NavWindowingTarget;
8043*61046927SAndroid Build Coastguard Worker     }
8044*61046927SAndroid Build Coastguard Worker 
8045*61046927SAndroid Build Coastguard Worker     // Keyboard: Press and Release ALT to toggle menu layer
8046*61046927SAndroid Build Coastguard Worker     // 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
8047*61046927SAndroid Build Coastguard Worker     if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released))
8048*61046927SAndroid Build Coastguard Worker         if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev))
8049*61046927SAndroid Build Coastguard Worker             apply_toggle_layer = true;
8050*61046927SAndroid Build Coastguard Worker 
8051*61046927SAndroid Build Coastguard Worker     // Move window
8052*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
8053*61046927SAndroid Build Coastguard Worker     {
8054*61046927SAndroid Build Coastguard Worker         ImVec2 move_delta;
8055*61046927SAndroid Build Coastguard Worker         if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift)
8056*61046927SAndroid Build Coastguard Worker             move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
8057*61046927SAndroid Build Coastguard Worker         if (g.NavInputSource == ImGuiInputSource_NavGamepad)
8058*61046927SAndroid Build Coastguard Worker             move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
8059*61046927SAndroid Build Coastguard Worker         if (move_delta.x != 0.0f || move_delta.y != 0.0f)
8060*61046927SAndroid Build Coastguard Worker         {
8061*61046927SAndroid Build Coastguard Worker             const float NAV_MOVE_SPEED = 800.0f;
8062*61046927SAndroid Build Coastguard Worker             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
8063*61046927SAndroid Build Coastguard Worker             g.NavWindowingTarget->RootWindow->Pos += move_delta * move_speed;
8064*61046927SAndroid Build Coastguard Worker             g.NavDisableMouseHover = true;
8065*61046927SAndroid Build Coastguard Worker             MarkIniSettingsDirty(g.NavWindowingTarget);
8066*61046927SAndroid Build Coastguard Worker         }
8067*61046927SAndroid Build Coastguard Worker     }
8068*61046927SAndroid Build Coastguard Worker 
8069*61046927SAndroid Build Coastguard Worker     // Apply final focus
8070*61046927SAndroid Build Coastguard Worker     if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
8071*61046927SAndroid Build Coastguard Worker     {
8072*61046927SAndroid Build Coastguard Worker         g.NavDisableHighlight = false;
8073*61046927SAndroid Build Coastguard Worker         g.NavDisableMouseHover = true;
8074*61046927SAndroid Build Coastguard Worker         apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
8075*61046927SAndroid Build Coastguard Worker         ClosePopupsOverWindow(apply_focus_window);
8076*61046927SAndroid Build Coastguard Worker         FocusWindow(apply_focus_window);
8077*61046927SAndroid Build Coastguard Worker         if (apply_focus_window->NavLastIds[0] == 0)
8078*61046927SAndroid Build Coastguard Worker             NavInitWindow(apply_focus_window, false);
8079*61046927SAndroid Build Coastguard Worker 
8080*61046927SAndroid Build Coastguard Worker         // If the window only has a menu layer, select it directly
8081*61046927SAndroid Build Coastguard Worker         if (apply_focus_window->DC.NavLayerActiveMask == (1 << ImGuiNavLayer_Menu))
8082*61046927SAndroid Build Coastguard Worker             g.NavLayer = ImGuiNavLayer_Menu;
8083*61046927SAndroid Build Coastguard Worker     }
8084*61046927SAndroid Build Coastguard Worker     if (apply_focus_window)
8085*61046927SAndroid Build Coastguard Worker         g.NavWindowingTarget = NULL;
8086*61046927SAndroid Build Coastguard Worker 
8087*61046927SAndroid Build Coastguard Worker     // Apply menu/layer toggle
8088*61046927SAndroid Build Coastguard Worker     if (apply_toggle_layer && g.NavWindow)
8089*61046927SAndroid Build Coastguard Worker     {
8090*61046927SAndroid Build Coastguard Worker         // Move to parent menu if necessary
8091*61046927SAndroid Build Coastguard Worker         ImGuiWindow* new_nav_window = g.NavWindow;
8092*61046927SAndroid Build Coastguard Worker         while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0
8093*61046927SAndroid Build Coastguard Worker             && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
8094*61046927SAndroid Build Coastguard Worker             && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
8095*61046927SAndroid Build Coastguard Worker             new_nav_window = new_nav_window->ParentWindow;
8096*61046927SAndroid Build Coastguard Worker         if (new_nav_window != g.NavWindow)
8097*61046927SAndroid Build Coastguard Worker         {
8098*61046927SAndroid Build Coastguard Worker             ImGuiWindow* old_nav_window = g.NavWindow;
8099*61046927SAndroid Build Coastguard Worker             FocusWindow(new_nav_window);
8100*61046927SAndroid Build Coastguard Worker             new_nav_window->NavLastChildNavWindow = old_nav_window;
8101*61046927SAndroid Build Coastguard Worker         }
8102*61046927SAndroid Build Coastguard Worker         g.NavDisableHighlight = false;
8103*61046927SAndroid Build Coastguard Worker         g.NavDisableMouseHover = true;
8104*61046927SAndroid Build Coastguard Worker         NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main);
8105*61046927SAndroid Build Coastguard Worker     }
8106*61046927SAndroid Build Coastguard Worker }
8107*61046927SAndroid Build Coastguard Worker 
8108*61046927SAndroid Build Coastguard Worker // Window has already passed the IsWindowNavFocusable()
GetFallbackWindowNameForWindowingList(ImGuiWindow * window)8109*61046927SAndroid Build Coastguard Worker static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
8110*61046927SAndroid Build Coastguard Worker {
8111*61046927SAndroid Build Coastguard Worker     if (window->Flags & ImGuiWindowFlags_Popup)
8112*61046927SAndroid Build Coastguard Worker         return "(Popup)";
8113*61046927SAndroid Build Coastguard Worker     if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0)
8114*61046927SAndroid Build Coastguard Worker         return "(Main menu bar)";
8115*61046927SAndroid Build Coastguard Worker     return "(Untitled)";
8116*61046927SAndroid Build Coastguard Worker }
8117*61046927SAndroid Build Coastguard Worker 
8118*61046927SAndroid Build Coastguard Worker // Overlay displayed when using CTRL+TAB. Called by EndFrame().
NavUpdateWindowingList()8119*61046927SAndroid Build Coastguard Worker void ImGui::NavUpdateWindowingList()
8120*61046927SAndroid Build Coastguard Worker {
8121*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8122*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.NavWindowingTarget != NULL);
8123*61046927SAndroid Build Coastguard Worker 
8124*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
8125*61046927SAndroid Build Coastguard Worker         return;
8126*61046927SAndroid Build Coastguard Worker 
8127*61046927SAndroid Build Coastguard Worker     if (g.NavWindowingList == NULL)
8128*61046927SAndroid Build Coastguard Worker         g.NavWindowingList = FindWindowByName("###NavWindowingList");
8129*61046927SAndroid Build Coastguard Worker     SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
8130*61046927SAndroid Build Coastguard Worker     SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
8131*61046927SAndroid Build Coastguard Worker     PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
8132*61046927SAndroid Build Coastguard Worker     Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
8133*61046927SAndroid Build Coastguard Worker     for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
8134*61046927SAndroid Build Coastguard Worker     {
8135*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.WindowsFocusOrder[n];
8136*61046927SAndroid Build Coastguard Worker         if (!IsWindowNavFocusable(window))
8137*61046927SAndroid Build Coastguard Worker             continue;
8138*61046927SAndroid Build Coastguard Worker         const char* label = window->Name;
8139*61046927SAndroid Build Coastguard Worker         if (label == FindRenderedTextEnd(label))
8140*61046927SAndroid Build Coastguard Worker             label = GetFallbackWindowNameForWindowingList(window);
8141*61046927SAndroid Build Coastguard Worker         Selectable(label, g.NavWindowingTarget == window);
8142*61046927SAndroid Build Coastguard Worker     }
8143*61046927SAndroid Build Coastguard Worker     End();
8144*61046927SAndroid Build Coastguard Worker     PopStyleVar();
8145*61046927SAndroid Build Coastguard Worker }
8146*61046927SAndroid Build Coastguard Worker 
8147*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8148*61046927SAndroid Build Coastguard Worker // [SECTION] COLUMNS
8149*61046927SAndroid Build Coastguard Worker // In the current version, Columns are very weak. Needs to be replaced with a more full-featured system.
8150*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8151*61046927SAndroid Build Coastguard Worker 
NextColumn()8152*61046927SAndroid Build Coastguard Worker void ImGui::NextColumn()
8153*61046927SAndroid Build Coastguard Worker {
8154*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
8155*61046927SAndroid Build Coastguard Worker     if (window->SkipItems || window->DC.ColumnsSet == NULL)
8156*61046927SAndroid Build Coastguard Worker         return;
8157*61046927SAndroid Build Coastguard Worker 
8158*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8159*61046927SAndroid Build Coastguard Worker     PopItemWidth();
8160*61046927SAndroid Build Coastguard Worker     PopClipRect();
8161*61046927SAndroid Build Coastguard Worker 
8162*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8163*61046927SAndroid Build Coastguard Worker     columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8164*61046927SAndroid Build Coastguard Worker     if (++columns->Current < columns->Count)
8165*61046927SAndroid Build Coastguard Worker     {
8166*61046927SAndroid Build Coastguard Worker         // Columns 1+ cancel out IndentX
8167*61046927SAndroid Build Coastguard Worker         window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x;
8168*61046927SAndroid Build Coastguard Worker         window->DrawList->ChannelsSetCurrent(columns->Current);
8169*61046927SAndroid Build Coastguard Worker     }
8170*61046927SAndroid Build Coastguard Worker     else
8171*61046927SAndroid Build Coastguard Worker     {
8172*61046927SAndroid Build Coastguard Worker         window->DC.ColumnsOffset.x = 0.0f;
8173*61046927SAndroid Build Coastguard Worker         window->DrawList->ChannelsSetCurrent(0);
8174*61046927SAndroid Build Coastguard Worker         columns->Current = 0;
8175*61046927SAndroid Build Coastguard Worker         columns->LineMinY = columns->LineMaxY;
8176*61046927SAndroid Build Coastguard Worker     }
8177*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8178*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.y = columns->LineMinY;
8179*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
8180*61046927SAndroid Build Coastguard Worker     window->DC.CurrentLineTextBaseOffset = 0.0f;
8181*61046927SAndroid Build Coastguard Worker 
8182*61046927SAndroid Build Coastguard Worker     PushColumnClipRect();
8183*61046927SAndroid Build Coastguard Worker     PushItemWidth(GetColumnWidth() * 0.65f);  // FIXME: Move on columns setup
8184*61046927SAndroid Build Coastguard Worker }
8185*61046927SAndroid Build Coastguard Worker 
GetColumnIndex()8186*61046927SAndroid Build Coastguard Worker int ImGui::GetColumnIndex()
8187*61046927SAndroid Build Coastguard Worker {
8188*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8189*61046927SAndroid Build Coastguard Worker     return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0;
8190*61046927SAndroid Build Coastguard Worker }
8191*61046927SAndroid Build Coastguard Worker 
GetColumnsCount()8192*61046927SAndroid Build Coastguard Worker int ImGui::GetColumnsCount()
8193*61046927SAndroid Build Coastguard Worker {
8194*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8195*61046927SAndroid Build Coastguard Worker     return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1;
8196*61046927SAndroid Build Coastguard Worker }
8197*61046927SAndroid Build Coastguard Worker 
OffsetNormToPixels(const ImGuiColumnsSet * columns,float offset_norm)8198*61046927SAndroid Build Coastguard Worker static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm)
8199*61046927SAndroid Build Coastguard Worker {
8200*61046927SAndroid Build Coastguard Worker     return offset_norm * (columns->MaxX - columns->MinX);
8201*61046927SAndroid Build Coastguard Worker }
8202*61046927SAndroid Build Coastguard Worker 
PixelsToOffsetNorm(const ImGuiColumnsSet * columns,float offset)8203*61046927SAndroid Build Coastguard Worker static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset)
8204*61046927SAndroid Build Coastguard Worker {
8205*61046927SAndroid Build Coastguard Worker     return offset / (columns->MaxX - columns->MinX);
8206*61046927SAndroid Build Coastguard Worker }
8207*61046927SAndroid Build Coastguard Worker 
GetColumnsRectHalfWidth()8208*61046927SAndroid Build Coastguard Worker static inline float GetColumnsRectHalfWidth() { return 4.0f; }
8209*61046927SAndroid Build Coastguard Worker 
GetDraggedColumnOffset(ImGuiColumnsSet * columns,int column_index)8210*61046927SAndroid Build Coastguard Worker static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index)
8211*61046927SAndroid Build Coastguard Worker {
8212*61046927SAndroid Build Coastguard Worker     // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
8213*61046927SAndroid Build Coastguard Worker     // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
8214*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8215*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8216*61046927SAndroid Build Coastguard Worker     IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
8217*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
8218*61046927SAndroid Build Coastguard Worker 
8219*61046927SAndroid Build Coastguard Worker     float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x;
8220*61046927SAndroid Build Coastguard Worker     x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
8221*61046927SAndroid Build Coastguard Worker     if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths))
8222*61046927SAndroid Build Coastguard Worker         x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
8223*61046927SAndroid Build Coastguard Worker 
8224*61046927SAndroid Build Coastguard Worker     return x;
8225*61046927SAndroid Build Coastguard Worker }
8226*61046927SAndroid Build Coastguard Worker 
GetColumnOffset(int column_index)8227*61046927SAndroid Build Coastguard Worker float ImGui::GetColumnOffset(int column_index)
8228*61046927SAndroid Build Coastguard Worker {
8229*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8230*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8231*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns != NULL);
8232*61046927SAndroid Build Coastguard Worker 
8233*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8234*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8235*61046927SAndroid Build Coastguard Worker     IM_ASSERT(column_index < columns->Columns.Size);
8236*61046927SAndroid Build Coastguard Worker 
8237*61046927SAndroid Build Coastguard Worker     const float t = columns->Columns[column_index].OffsetNorm;
8238*61046927SAndroid Build Coastguard Worker     const float x_offset = ImLerp(columns->MinX, columns->MaxX, t);
8239*61046927SAndroid Build Coastguard Worker     return x_offset;
8240*61046927SAndroid Build Coastguard Worker }
8241*61046927SAndroid Build Coastguard Worker 
GetColumnWidthEx(ImGuiColumnsSet * columns,int column_index,bool before_resize=false)8242*61046927SAndroid Build Coastguard Worker static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false)
8243*61046927SAndroid Build Coastguard Worker {
8244*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8245*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8246*61046927SAndroid Build Coastguard Worker 
8247*61046927SAndroid Build Coastguard Worker     float offset_norm;
8248*61046927SAndroid Build Coastguard Worker     if (before_resize)
8249*61046927SAndroid Build Coastguard Worker         offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize;
8250*61046927SAndroid Build Coastguard Worker     else
8251*61046927SAndroid Build Coastguard Worker         offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm;
8252*61046927SAndroid Build Coastguard Worker     return OffsetNormToPixels(columns, offset_norm);
8253*61046927SAndroid Build Coastguard Worker }
8254*61046927SAndroid Build Coastguard Worker 
GetColumnWidth(int column_index)8255*61046927SAndroid Build Coastguard Worker float ImGui::GetColumnWidth(int column_index)
8256*61046927SAndroid Build Coastguard Worker {
8257*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8258*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8259*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns != NULL);
8260*61046927SAndroid Build Coastguard Worker 
8261*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8262*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8263*61046927SAndroid Build Coastguard Worker     return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm);
8264*61046927SAndroid Build Coastguard Worker }
8265*61046927SAndroid Build Coastguard Worker 
SetColumnOffset(int column_index,float offset)8266*61046927SAndroid Build Coastguard Worker void ImGui::SetColumnOffset(int column_index, float offset)
8267*61046927SAndroid Build Coastguard Worker {
8268*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8269*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8270*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8271*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns != NULL);
8272*61046927SAndroid Build Coastguard Worker 
8273*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8274*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8275*61046927SAndroid Build Coastguard Worker     IM_ASSERT(column_index < columns->Columns.Size);
8276*61046927SAndroid Build Coastguard Worker 
8277*61046927SAndroid Build Coastguard Worker     const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1);
8278*61046927SAndroid Build Coastguard Worker     const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
8279*61046927SAndroid Build Coastguard Worker 
8280*61046927SAndroid Build Coastguard Worker     if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
8281*61046927SAndroid Build Coastguard Worker         offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
8282*61046927SAndroid Build Coastguard Worker     columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX);
8283*61046927SAndroid Build Coastguard Worker 
8284*61046927SAndroid Build Coastguard Worker     if (preserve_width)
8285*61046927SAndroid Build Coastguard Worker         SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
8286*61046927SAndroid Build Coastguard Worker }
8287*61046927SAndroid Build Coastguard Worker 
SetColumnWidth(int column_index,float width)8288*61046927SAndroid Build Coastguard Worker void ImGui::SetColumnWidth(int column_index, float width)
8289*61046927SAndroid Build Coastguard Worker {
8290*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8291*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8292*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns != NULL);
8293*61046927SAndroid Build Coastguard Worker 
8294*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8295*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8296*61046927SAndroid Build Coastguard Worker     SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width);
8297*61046927SAndroid Build Coastguard Worker }
8298*61046927SAndroid Build Coastguard Worker 
PushColumnClipRect(int column_index)8299*61046927SAndroid Build Coastguard Worker void ImGui::PushColumnClipRect(int column_index)
8300*61046927SAndroid Build Coastguard Worker {
8301*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindowRead();
8302*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8303*61046927SAndroid Build Coastguard Worker     if (column_index < 0)
8304*61046927SAndroid Build Coastguard Worker         column_index = columns->Current;
8305*61046927SAndroid Build Coastguard Worker 
8306*61046927SAndroid Build Coastguard Worker     PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false);
8307*61046927SAndroid Build Coastguard Worker }
8308*61046927SAndroid Build Coastguard Worker 
FindOrAddColumnsSet(ImGuiWindow * window,ImGuiID id)8309*61046927SAndroid Build Coastguard Worker static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id)
8310*61046927SAndroid Build Coastguard Worker {
8311*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < window->ColumnsStorage.Size; n++)
8312*61046927SAndroid Build Coastguard Worker         if (window->ColumnsStorage[n].ID == id)
8313*61046927SAndroid Build Coastguard Worker             return &window->ColumnsStorage[n];
8314*61046927SAndroid Build Coastguard Worker 
8315*61046927SAndroid Build Coastguard Worker     window->ColumnsStorage.push_back(ImGuiColumnsSet());
8316*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = &window->ColumnsStorage.back();
8317*61046927SAndroid Build Coastguard Worker     columns->ID = id;
8318*61046927SAndroid Build Coastguard Worker     return columns;
8319*61046927SAndroid Build Coastguard Worker }
8320*61046927SAndroid Build Coastguard Worker 
BeginColumns(const char * str_id,int columns_count,ImGuiColumnsFlags flags)8321*61046927SAndroid Build Coastguard Worker void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags)
8322*61046927SAndroid Build Coastguard Worker {
8323*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8324*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
8325*61046927SAndroid Build Coastguard Worker 
8326*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns_count > 1);
8327*61046927SAndroid Build Coastguard Worker     IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported
8328*61046927SAndroid Build Coastguard Worker 
8329*61046927SAndroid Build Coastguard Worker     // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.
8330*61046927SAndroid Build Coastguard Worker     // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.
8331*61046927SAndroid Build Coastguard Worker     PushID(0x11223347 + (str_id ? 0 : columns_count));
8332*61046927SAndroid Build Coastguard Worker     ImGuiID id = window->GetID(str_id ? str_id : "columns");
8333*61046927SAndroid Build Coastguard Worker     PopID();
8334*61046927SAndroid Build Coastguard Worker 
8335*61046927SAndroid Build Coastguard Worker     // Acquire storage for the columns set
8336*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id);
8337*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns->ID == id);
8338*61046927SAndroid Build Coastguard Worker     columns->Current = 0;
8339*61046927SAndroid Build Coastguard Worker     columns->Count = columns_count;
8340*61046927SAndroid Build Coastguard Worker     columns->Flags = flags;
8341*61046927SAndroid Build Coastguard Worker     window->DC.ColumnsSet = columns;
8342*61046927SAndroid Build Coastguard Worker 
8343*61046927SAndroid Build Coastguard Worker     // Set state for first column
8344*61046927SAndroid Build Coastguard Worker     const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x);
8345*61046927SAndroid Build Coastguard Worker     columns->MinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
8346*61046927SAndroid Build Coastguard Worker     columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f);
8347*61046927SAndroid Build Coastguard Worker     columns->StartPosY = window->DC.CursorPos.y;
8348*61046927SAndroid Build Coastguard Worker     columns->StartMaxPosX = window->DC.CursorMaxPos.x;
8349*61046927SAndroid Build Coastguard Worker     columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
8350*61046927SAndroid Build Coastguard Worker     window->DC.ColumnsOffset.x = 0.0f;
8351*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8352*61046927SAndroid Build Coastguard Worker 
8353*61046927SAndroid Build Coastguard Worker     // Clear data if columns count changed
8354*61046927SAndroid Build Coastguard Worker     if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
8355*61046927SAndroid Build Coastguard Worker         columns->Columns.resize(0);
8356*61046927SAndroid Build Coastguard Worker 
8357*61046927SAndroid Build Coastguard Worker     // Initialize defaults
8358*61046927SAndroid Build Coastguard Worker     columns->IsFirstFrame = (columns->Columns.Size == 0);
8359*61046927SAndroid Build Coastguard Worker     if (columns->Columns.Size == 0)
8360*61046927SAndroid Build Coastguard Worker     {
8361*61046927SAndroid Build Coastguard Worker         columns->Columns.reserve(columns_count + 1);
8362*61046927SAndroid Build Coastguard Worker         for (int n = 0; n < columns_count + 1; n++)
8363*61046927SAndroid Build Coastguard Worker         {
8364*61046927SAndroid Build Coastguard Worker             ImGuiColumnData column;
8365*61046927SAndroid Build Coastguard Worker             column.OffsetNorm = n / (float)columns_count;
8366*61046927SAndroid Build Coastguard Worker             columns->Columns.push_back(column);
8367*61046927SAndroid Build Coastguard Worker         }
8368*61046927SAndroid Build Coastguard Worker     }
8369*61046927SAndroid Build Coastguard Worker 
8370*61046927SAndroid Build Coastguard Worker     for (int n = 0; n < columns_count; n++)
8371*61046927SAndroid Build Coastguard Worker     {
8372*61046927SAndroid Build Coastguard Worker         // Compute clipping rectangle
8373*61046927SAndroid Build Coastguard Worker         ImGuiColumnData* column = &columns->Columns[n];
8374*61046927SAndroid Build Coastguard Worker         float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f);
8375*61046927SAndroid Build Coastguard Worker         float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
8376*61046927SAndroid Build Coastguard Worker         column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
8377*61046927SAndroid Build Coastguard Worker         column->ClipRect.ClipWith(window->ClipRect);
8378*61046927SAndroid Build Coastguard Worker     }
8379*61046927SAndroid Build Coastguard Worker 
8380*61046927SAndroid Build Coastguard Worker     window->DrawList->ChannelsSplit(columns->Count);
8381*61046927SAndroid Build Coastguard Worker     PushColumnClipRect();
8382*61046927SAndroid Build Coastguard Worker     PushItemWidth(GetColumnWidth() * 0.65f);
8383*61046927SAndroid Build Coastguard Worker }
8384*61046927SAndroid Build Coastguard Worker 
EndColumns()8385*61046927SAndroid Build Coastguard Worker void ImGui::EndColumns()
8386*61046927SAndroid Build Coastguard Worker {
8387*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8388*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
8389*61046927SAndroid Build Coastguard Worker     ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8390*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns != NULL);
8391*61046927SAndroid Build Coastguard Worker 
8392*61046927SAndroid Build Coastguard Worker     PopItemWidth();
8393*61046927SAndroid Build Coastguard Worker     PopClipRect();
8394*61046927SAndroid Build Coastguard Worker     window->DrawList->ChannelsMerge();
8395*61046927SAndroid Build Coastguard Worker 
8396*61046927SAndroid Build Coastguard Worker     columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8397*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.y = columns->LineMaxY;
8398*61046927SAndroid Build Coastguard Worker     if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize))
8399*61046927SAndroid Build Coastguard Worker         window->DC.CursorMaxPos.x = columns->StartMaxPosX;  // Restore cursor max pos, as columns don't grow parent
8400*61046927SAndroid Build Coastguard Worker 
8401*61046927SAndroid Build Coastguard Worker     // Draw columns borders and handle resize
8402*61046927SAndroid Build Coastguard Worker     bool is_being_resized = false;
8403*61046927SAndroid Build Coastguard Worker     if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
8404*61046927SAndroid Build Coastguard Worker     {
8405*61046927SAndroid Build Coastguard Worker         const float y1 = columns->StartPosY;
8406*61046927SAndroid Build Coastguard Worker         const float y2 = window->DC.CursorPos.y;
8407*61046927SAndroid Build Coastguard Worker         int dragging_column = -1;
8408*61046927SAndroid Build Coastguard Worker         for (int n = 1; n < columns->Count; n++)
8409*61046927SAndroid Build Coastguard Worker         {
8410*61046927SAndroid Build Coastguard Worker             float x = window->Pos.x + GetColumnOffset(n);
8411*61046927SAndroid Build Coastguard Worker             const ImGuiID column_id = columns->ID + ImGuiID(n);
8412*61046927SAndroid Build Coastguard Worker             const float column_hw = GetColumnsRectHalfWidth(); // Half-width for interaction
8413*61046927SAndroid Build Coastguard Worker             const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2));
8414*61046927SAndroid Build Coastguard Worker             KeepAliveID(column_id);
8415*61046927SAndroid Build Coastguard Worker             if (IsClippedEx(column_rect, column_id, false))
8416*61046927SAndroid Build Coastguard Worker                 continue;
8417*61046927SAndroid Build Coastguard Worker 
8418*61046927SAndroid Build Coastguard Worker             bool hovered = false, held = false;
8419*61046927SAndroid Build Coastguard Worker             if (!(columns->Flags & ImGuiColumnsFlags_NoResize))
8420*61046927SAndroid Build Coastguard Worker             {
8421*61046927SAndroid Build Coastguard Worker                 ButtonBehavior(column_rect, column_id, &hovered, &held);
8422*61046927SAndroid Build Coastguard Worker                 if (hovered || held)
8423*61046927SAndroid Build Coastguard Worker                     g.MouseCursor = ImGuiMouseCursor_ResizeEW;
8424*61046927SAndroid Build Coastguard Worker                 if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize))
8425*61046927SAndroid Build Coastguard Worker                     dragging_column = n;
8426*61046927SAndroid Build Coastguard Worker             }
8427*61046927SAndroid Build Coastguard Worker 
8428*61046927SAndroid Build Coastguard Worker             // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.)
8429*61046927SAndroid Build Coastguard Worker             const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
8430*61046927SAndroid Build Coastguard Worker             const float xi = (float)(int)x;
8431*61046927SAndroid Build Coastguard Worker             window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col);
8432*61046927SAndroid Build Coastguard Worker         }
8433*61046927SAndroid Build Coastguard Worker 
8434*61046927SAndroid Build Coastguard Worker         // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
8435*61046927SAndroid Build Coastguard Worker         if (dragging_column != -1)
8436*61046927SAndroid Build Coastguard Worker         {
8437*61046927SAndroid Build Coastguard Worker             if (!columns->IsBeingResized)
8438*61046927SAndroid Build Coastguard Worker                 for (int n = 0; n < columns->Count + 1; n++)
8439*61046927SAndroid Build Coastguard Worker                     columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm;
8440*61046927SAndroid Build Coastguard Worker             columns->IsBeingResized = is_being_resized = true;
8441*61046927SAndroid Build Coastguard Worker             float x = GetDraggedColumnOffset(columns, dragging_column);
8442*61046927SAndroid Build Coastguard Worker             SetColumnOffset(dragging_column, x);
8443*61046927SAndroid Build Coastguard Worker         }
8444*61046927SAndroid Build Coastguard Worker     }
8445*61046927SAndroid Build Coastguard Worker     columns->IsBeingResized = is_being_resized;
8446*61046927SAndroid Build Coastguard Worker 
8447*61046927SAndroid Build Coastguard Worker     window->DC.ColumnsSet = NULL;
8448*61046927SAndroid Build Coastguard Worker     window->DC.ColumnsOffset.x = 0.0f;
8449*61046927SAndroid Build Coastguard Worker     window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8450*61046927SAndroid Build Coastguard Worker }
8451*61046927SAndroid Build Coastguard Worker 
8452*61046927SAndroid Build Coastguard Worker // [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]
Columns(int columns_count,const char * id,bool border)8453*61046927SAndroid Build Coastguard Worker void ImGui::Columns(int columns_count, const char* id, bool border)
8454*61046927SAndroid Build Coastguard Worker {
8455*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = GetCurrentWindow();
8456*61046927SAndroid Build Coastguard Worker     IM_ASSERT(columns_count >= 1);
8457*61046927SAndroid Build Coastguard Worker 
8458*61046927SAndroid Build Coastguard Worker     ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
8459*61046927SAndroid Build Coastguard Worker     //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
8460*61046927SAndroid Build Coastguard Worker     if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags)
8461*61046927SAndroid Build Coastguard Worker         return;
8462*61046927SAndroid Build Coastguard Worker 
8463*61046927SAndroid Build Coastguard Worker     if (window->DC.ColumnsSet != NULL)
8464*61046927SAndroid Build Coastguard Worker         EndColumns();
8465*61046927SAndroid Build Coastguard Worker 
8466*61046927SAndroid Build Coastguard Worker     if (columns_count != 1)
8467*61046927SAndroid Build Coastguard Worker         BeginColumns(id, columns_count, flags);
8468*61046927SAndroid Build Coastguard Worker }
8469*61046927SAndroid Build Coastguard Worker 
8470*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8471*61046927SAndroid Build Coastguard Worker // [SECTION] DRAG AND DROP
8472*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8473*61046927SAndroid Build Coastguard Worker 
ClearDragDrop()8474*61046927SAndroid Build Coastguard Worker void ImGui::ClearDragDrop()
8475*61046927SAndroid Build Coastguard Worker {
8476*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8477*61046927SAndroid Build Coastguard Worker     g.DragDropActive = false;
8478*61046927SAndroid Build Coastguard Worker     g.DragDropPayload.Clear();
8479*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
8480*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0;
8481*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
8482*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptFrameCount = -1;
8483*61046927SAndroid Build Coastguard Worker 
8484*61046927SAndroid Build Coastguard Worker     g.DragDropPayloadBufHeap.clear();
8485*61046927SAndroid Build Coastguard Worker     memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
8486*61046927SAndroid Build Coastguard Worker }
8487*61046927SAndroid Build Coastguard Worker 
8488*61046927SAndroid Build Coastguard Worker // Call when current ID is active.
8489*61046927SAndroid Build Coastguard Worker // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
BeginDragDropSource(ImGuiDragDropFlags flags)8490*61046927SAndroid Build Coastguard Worker bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
8491*61046927SAndroid Build Coastguard Worker {
8492*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8493*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8494*61046927SAndroid Build Coastguard Worker 
8495*61046927SAndroid Build Coastguard Worker     bool source_drag_active = false;
8496*61046927SAndroid Build Coastguard Worker     ImGuiID source_id = 0;
8497*61046927SAndroid Build Coastguard Worker     ImGuiID source_parent_id = 0;
8498*61046927SAndroid Build Coastguard Worker     int mouse_button = 0;
8499*61046927SAndroid Build Coastguard Worker     if (!(flags & ImGuiDragDropFlags_SourceExtern))
8500*61046927SAndroid Build Coastguard Worker     {
8501*61046927SAndroid Build Coastguard Worker         source_id = window->DC.LastItemId;
8502*61046927SAndroid Build Coastguard Worker         if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
8503*61046927SAndroid Build Coastguard Worker             return false;
8504*61046927SAndroid Build Coastguard Worker         if (g.IO.MouseDown[mouse_button] == false)
8505*61046927SAndroid Build Coastguard Worker             return false;
8506*61046927SAndroid Build Coastguard Worker 
8507*61046927SAndroid Build Coastguard Worker         if (source_id == 0)
8508*61046927SAndroid Build Coastguard Worker         {
8509*61046927SAndroid Build Coastguard Worker             // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
8510*61046927SAndroid Build Coastguard Worker             // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
8511*61046927SAndroid Build Coastguard Worker             if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
8512*61046927SAndroid Build Coastguard Worker             {
8513*61046927SAndroid Build Coastguard Worker                 IM_ASSERT(0);
8514*61046927SAndroid Build Coastguard Worker                 return false;
8515*61046927SAndroid Build Coastguard Worker             }
8516*61046927SAndroid Build Coastguard Worker 
8517*61046927SAndroid Build Coastguard Worker             // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
8518*61046927SAndroid Build Coastguard Worker             // We build a throwaway ID based on current ID stack + relative AABB of items in window.
8519*61046927SAndroid Build Coastguard Worker             // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
8520*61046927SAndroid Build Coastguard Worker             // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
8521*61046927SAndroid Build Coastguard Worker             bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0;
8522*61046927SAndroid Build Coastguard Worker             if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
8523*61046927SAndroid Build Coastguard Worker                 return false;
8524*61046927SAndroid Build Coastguard Worker             source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
8525*61046927SAndroid Build Coastguard Worker             if (is_hovered)
8526*61046927SAndroid Build Coastguard Worker                 SetHoveredID(source_id);
8527*61046927SAndroid Build Coastguard Worker             if (is_hovered && g.IO.MouseClicked[mouse_button])
8528*61046927SAndroid Build Coastguard Worker             {
8529*61046927SAndroid Build Coastguard Worker                 SetActiveID(source_id, window);
8530*61046927SAndroid Build Coastguard Worker                 FocusWindow(window);
8531*61046927SAndroid Build Coastguard Worker             }
8532*61046927SAndroid Build Coastguard Worker             if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
8533*61046927SAndroid Build Coastguard Worker                 g.ActiveIdAllowOverlap = is_hovered;
8534*61046927SAndroid Build Coastguard Worker         }
8535*61046927SAndroid Build Coastguard Worker         else
8536*61046927SAndroid Build Coastguard Worker         {
8537*61046927SAndroid Build Coastguard Worker             g.ActiveIdAllowOverlap = false;
8538*61046927SAndroid Build Coastguard Worker         }
8539*61046927SAndroid Build Coastguard Worker         if (g.ActiveId != source_id)
8540*61046927SAndroid Build Coastguard Worker             return false;
8541*61046927SAndroid Build Coastguard Worker         source_parent_id = window->IDStack.back();
8542*61046927SAndroid Build Coastguard Worker         source_drag_active = IsMouseDragging(mouse_button);
8543*61046927SAndroid Build Coastguard Worker     }
8544*61046927SAndroid Build Coastguard Worker     else
8545*61046927SAndroid Build Coastguard Worker     {
8546*61046927SAndroid Build Coastguard Worker         window = NULL;
8547*61046927SAndroid Build Coastguard Worker         source_id = ImHashStr("#SourceExtern", 0);
8548*61046927SAndroid Build Coastguard Worker         source_drag_active = true;
8549*61046927SAndroid Build Coastguard Worker     }
8550*61046927SAndroid Build Coastguard Worker 
8551*61046927SAndroid Build Coastguard Worker     if (source_drag_active)
8552*61046927SAndroid Build Coastguard Worker     {
8553*61046927SAndroid Build Coastguard Worker         if (!g.DragDropActive)
8554*61046927SAndroid Build Coastguard Worker         {
8555*61046927SAndroid Build Coastguard Worker             IM_ASSERT(source_id != 0);
8556*61046927SAndroid Build Coastguard Worker             ClearDragDrop();
8557*61046927SAndroid Build Coastguard Worker             ImGuiPayload& payload = g.DragDropPayload;
8558*61046927SAndroid Build Coastguard Worker             payload.SourceId = source_id;
8559*61046927SAndroid Build Coastguard Worker             payload.SourceParentId = source_parent_id;
8560*61046927SAndroid Build Coastguard Worker             g.DragDropActive = true;
8561*61046927SAndroid Build Coastguard Worker             g.DragDropSourceFlags = flags;
8562*61046927SAndroid Build Coastguard Worker             g.DragDropMouseButton = mouse_button;
8563*61046927SAndroid Build Coastguard Worker         }
8564*61046927SAndroid Build Coastguard Worker         g.DragDropSourceFrameCount = g.FrameCount;
8565*61046927SAndroid Build Coastguard Worker         g.DragDropWithinSourceOrTarget = true;
8566*61046927SAndroid Build Coastguard Worker 
8567*61046927SAndroid Build Coastguard Worker         if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
8568*61046927SAndroid Build Coastguard Worker         {
8569*61046927SAndroid Build Coastguard Worker             // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
8570*61046927SAndroid Build Coastguard Worker             // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
8571*61046927SAndroid Build Coastguard Worker             BeginTooltip();
8572*61046927SAndroid Build Coastguard Worker             if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
8573*61046927SAndroid Build Coastguard Worker             {
8574*61046927SAndroid Build Coastguard Worker                 ImGuiWindow* tooltip_window = g.CurrentWindow;
8575*61046927SAndroid Build Coastguard Worker                 tooltip_window->SkipItems = true;
8576*61046927SAndroid Build Coastguard Worker                 tooltip_window->HiddenFramesRegular = 1;
8577*61046927SAndroid Build Coastguard Worker             }
8578*61046927SAndroid Build Coastguard Worker         }
8579*61046927SAndroid Build Coastguard Worker 
8580*61046927SAndroid Build Coastguard Worker         if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
8581*61046927SAndroid Build Coastguard Worker             window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
8582*61046927SAndroid Build Coastguard Worker 
8583*61046927SAndroid Build Coastguard Worker         return true;
8584*61046927SAndroid Build Coastguard Worker     }
8585*61046927SAndroid Build Coastguard Worker     return false;
8586*61046927SAndroid Build Coastguard Worker }
8587*61046927SAndroid Build Coastguard Worker 
EndDragDropSource()8588*61046927SAndroid Build Coastguard Worker void ImGui::EndDragDropSource()
8589*61046927SAndroid Build Coastguard Worker {
8590*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8591*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropActive);
8592*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropWithinSourceOrTarget && "Not after a BeginDragDropSource()?");
8593*61046927SAndroid Build Coastguard Worker 
8594*61046927SAndroid Build Coastguard Worker     if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
8595*61046927SAndroid Build Coastguard Worker         EndTooltip();
8596*61046927SAndroid Build Coastguard Worker 
8597*61046927SAndroid Build Coastguard Worker     // Discard the drag if have not called SetDragDropPayload()
8598*61046927SAndroid Build Coastguard Worker     if (g.DragDropPayload.DataFrameCount == -1)
8599*61046927SAndroid Build Coastguard Worker         ClearDragDrop();
8600*61046927SAndroid Build Coastguard Worker     g.DragDropWithinSourceOrTarget = false;
8601*61046927SAndroid Build Coastguard Worker }
8602*61046927SAndroid Build Coastguard Worker 
8603*61046927SAndroid Build Coastguard Worker // Use 'cond' to choose to submit payload on drag start or every frame
SetDragDropPayload(const char * type,const void * data,size_t data_size,ImGuiCond cond)8604*61046927SAndroid Build Coastguard Worker bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
8605*61046927SAndroid Build Coastguard Worker {
8606*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8607*61046927SAndroid Build Coastguard Worker     ImGuiPayload& payload = g.DragDropPayload;
8608*61046927SAndroid Build Coastguard Worker     if (cond == 0)
8609*61046927SAndroid Build Coastguard Worker         cond = ImGuiCond_Always;
8610*61046927SAndroid Build Coastguard Worker 
8611*61046927SAndroid Build Coastguard Worker     IM_ASSERT(type != NULL);
8612*61046927SAndroid Build Coastguard Worker     IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
8613*61046927SAndroid Build Coastguard Worker     IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
8614*61046927SAndroid Build Coastguard Worker     IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
8615*61046927SAndroid Build Coastguard Worker     IM_ASSERT(payload.SourceId != 0);                               // Not called between BeginDragDropSource() and EndDragDropSource()
8616*61046927SAndroid Build Coastguard Worker 
8617*61046927SAndroid Build Coastguard Worker     if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
8618*61046927SAndroid Build Coastguard Worker     {
8619*61046927SAndroid Build Coastguard Worker         // Copy payload
8620*61046927SAndroid Build Coastguard Worker         ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
8621*61046927SAndroid Build Coastguard Worker         g.DragDropPayloadBufHeap.resize(0);
8622*61046927SAndroid Build Coastguard Worker         if (data_size > sizeof(g.DragDropPayloadBufLocal))
8623*61046927SAndroid Build Coastguard Worker         {
8624*61046927SAndroid Build Coastguard Worker             // Store in heap
8625*61046927SAndroid Build Coastguard Worker             g.DragDropPayloadBufHeap.resize((int)data_size);
8626*61046927SAndroid Build Coastguard Worker             payload.Data = g.DragDropPayloadBufHeap.Data;
8627*61046927SAndroid Build Coastguard Worker             memcpy(payload.Data, data, data_size);
8628*61046927SAndroid Build Coastguard Worker         }
8629*61046927SAndroid Build Coastguard Worker         else if (data_size > 0)
8630*61046927SAndroid Build Coastguard Worker         {
8631*61046927SAndroid Build Coastguard Worker             // Store locally
8632*61046927SAndroid Build Coastguard Worker             memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
8633*61046927SAndroid Build Coastguard Worker             payload.Data = g.DragDropPayloadBufLocal;
8634*61046927SAndroid Build Coastguard Worker             memcpy(payload.Data, data, data_size);
8635*61046927SAndroid Build Coastguard Worker         }
8636*61046927SAndroid Build Coastguard Worker         else
8637*61046927SAndroid Build Coastguard Worker         {
8638*61046927SAndroid Build Coastguard Worker             payload.Data = NULL;
8639*61046927SAndroid Build Coastguard Worker         }
8640*61046927SAndroid Build Coastguard Worker         payload.DataSize = (int)data_size;
8641*61046927SAndroid Build Coastguard Worker     }
8642*61046927SAndroid Build Coastguard Worker     payload.DataFrameCount = g.FrameCount;
8643*61046927SAndroid Build Coastguard Worker 
8644*61046927SAndroid Build Coastguard Worker     return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1);
8645*61046927SAndroid Build Coastguard Worker }
8646*61046927SAndroid Build Coastguard Worker 
BeginDragDropTargetCustom(const ImRect & bb,ImGuiID id)8647*61046927SAndroid Build Coastguard Worker bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
8648*61046927SAndroid Build Coastguard Worker {
8649*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8650*61046927SAndroid Build Coastguard Worker     if (!g.DragDropActive)
8651*61046927SAndroid Build Coastguard Worker         return false;
8652*61046927SAndroid Build Coastguard Worker 
8653*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8654*61046927SAndroid Build Coastguard Worker     if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8655*61046927SAndroid Build Coastguard Worker         return false;
8656*61046927SAndroid Build Coastguard Worker     IM_ASSERT(id != 0);
8657*61046927SAndroid Build Coastguard Worker     if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
8658*61046927SAndroid Build Coastguard Worker         return false;
8659*61046927SAndroid Build Coastguard Worker     if (window->SkipItems)
8660*61046927SAndroid Build Coastguard Worker         return false;
8661*61046927SAndroid Build Coastguard Worker 
8662*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropWithinSourceOrTarget == false);
8663*61046927SAndroid Build Coastguard Worker     g.DragDropTargetRect = bb;
8664*61046927SAndroid Build Coastguard Worker     g.DragDropTargetId = id;
8665*61046927SAndroid Build Coastguard Worker     g.DragDropWithinSourceOrTarget = true;
8666*61046927SAndroid Build Coastguard Worker     return true;
8667*61046927SAndroid Build Coastguard Worker }
8668*61046927SAndroid Build Coastguard Worker 
8669*61046927SAndroid Build Coastguard Worker // We don't use BeginDragDropTargetCustom() and duplicate its code because:
8670*61046927SAndroid Build Coastguard Worker // 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them.
8671*61046927SAndroid Build Coastguard Worker // 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can.
8672*61046927SAndroid Build Coastguard Worker // Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case)
BeginDragDropTarget()8673*61046927SAndroid Build Coastguard Worker bool ImGui::BeginDragDropTarget()
8674*61046927SAndroid Build Coastguard Worker {
8675*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8676*61046927SAndroid Build Coastguard Worker     if (!g.DragDropActive)
8677*61046927SAndroid Build Coastguard Worker         return false;
8678*61046927SAndroid Build Coastguard Worker 
8679*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8680*61046927SAndroid Build Coastguard Worker     if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
8681*61046927SAndroid Build Coastguard Worker         return false;
8682*61046927SAndroid Build Coastguard Worker     if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8683*61046927SAndroid Build Coastguard Worker         return false;
8684*61046927SAndroid Build Coastguard Worker 
8685*61046927SAndroid Build Coastguard Worker     const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
8686*61046927SAndroid Build Coastguard Worker     ImGuiID id = window->DC.LastItemId;
8687*61046927SAndroid Build Coastguard Worker     if (id == 0)
8688*61046927SAndroid Build Coastguard Worker         id = window->GetIDFromRectangle(display_rect);
8689*61046927SAndroid Build Coastguard Worker     if (g.DragDropPayload.SourceId == id)
8690*61046927SAndroid Build Coastguard Worker         return false;
8691*61046927SAndroid Build Coastguard Worker 
8692*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropWithinSourceOrTarget == false);
8693*61046927SAndroid Build Coastguard Worker     g.DragDropTargetRect = display_rect;
8694*61046927SAndroid Build Coastguard Worker     g.DragDropTargetId = id;
8695*61046927SAndroid Build Coastguard Worker     g.DragDropWithinSourceOrTarget = true;
8696*61046927SAndroid Build Coastguard Worker     return true;
8697*61046927SAndroid Build Coastguard Worker }
8698*61046927SAndroid Build Coastguard Worker 
IsDragDropPayloadBeingAccepted()8699*61046927SAndroid Build Coastguard Worker bool ImGui::IsDragDropPayloadBeingAccepted()
8700*61046927SAndroid Build Coastguard Worker {
8701*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8702*61046927SAndroid Build Coastguard Worker     return g.DragDropActive && g.DragDropAcceptIdPrev != 0;
8703*61046927SAndroid Build Coastguard Worker }
8704*61046927SAndroid Build Coastguard Worker 
AcceptDragDropPayload(const char * type,ImGuiDragDropFlags flags)8705*61046927SAndroid Build Coastguard Worker const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags)
8706*61046927SAndroid Build Coastguard Worker {
8707*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8708*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8709*61046927SAndroid Build Coastguard Worker     ImGuiPayload& payload = g.DragDropPayload;
8710*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropActive);                        // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
8711*61046927SAndroid Build Coastguard Worker     IM_ASSERT(payload.DataFrameCount != -1);            // Forgot to call EndDragDropTarget() ?
8712*61046927SAndroid Build Coastguard Worker     if (type != NULL && !payload.IsDataType(type))
8713*61046927SAndroid Build Coastguard Worker         return NULL;
8714*61046927SAndroid Build Coastguard Worker 
8715*61046927SAndroid Build Coastguard Worker     // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints.
8716*61046927SAndroid Build Coastguard Worker     // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function!
8717*61046927SAndroid Build Coastguard Worker     const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId);
8718*61046927SAndroid Build Coastguard Worker     ImRect r = g.DragDropTargetRect;
8719*61046927SAndroid Build Coastguard Worker     float r_surface = r.GetWidth() * r.GetHeight();
8720*61046927SAndroid Build Coastguard Worker     if (r_surface < g.DragDropAcceptIdCurrRectSurface)
8721*61046927SAndroid Build Coastguard Worker     {
8722*61046927SAndroid Build Coastguard Worker         g.DragDropAcceptFlags = flags;
8723*61046927SAndroid Build Coastguard Worker         g.DragDropAcceptIdCurr = g.DragDropTargetId;
8724*61046927SAndroid Build Coastguard Worker         g.DragDropAcceptIdCurrRectSurface = r_surface;
8725*61046927SAndroid Build Coastguard Worker     }
8726*61046927SAndroid Build Coastguard Worker 
8727*61046927SAndroid Build Coastguard Worker     // Render default drop visuals
8728*61046927SAndroid Build Coastguard Worker     payload.Preview = was_accepted_previously;
8729*61046927SAndroid Build Coastguard Worker     flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
8730*61046927SAndroid Build Coastguard Worker     if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
8731*61046927SAndroid Build Coastguard Worker     {
8732*61046927SAndroid Build Coastguard Worker         // FIXME-DRAG: Settle on a proper default visuals for drop target.
8733*61046927SAndroid Build Coastguard Worker         r.Expand(3.5f);
8734*61046927SAndroid Build Coastguard Worker         bool push_clip_rect = !window->ClipRect.Contains(r);
8735*61046927SAndroid Build Coastguard Worker         if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1));
8736*61046927SAndroid Build Coastguard Worker         window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
8737*61046927SAndroid Build Coastguard Worker         if (push_clip_rect) window->DrawList->PopClipRect();
8738*61046927SAndroid Build Coastguard Worker     }
8739*61046927SAndroid Build Coastguard Worker 
8740*61046927SAndroid Build Coastguard Worker     g.DragDropAcceptFrameCount = g.FrameCount;
8741*61046927SAndroid Build Coastguard Worker     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()
8742*61046927SAndroid Build Coastguard Worker     if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
8743*61046927SAndroid Build Coastguard Worker         return NULL;
8744*61046927SAndroid Build Coastguard Worker 
8745*61046927SAndroid Build Coastguard Worker     return &payload;
8746*61046927SAndroid Build Coastguard Worker }
8747*61046927SAndroid Build Coastguard Worker 
GetDragDropPayload()8748*61046927SAndroid Build Coastguard Worker const ImGuiPayload* ImGui::GetDragDropPayload()
8749*61046927SAndroid Build Coastguard Worker {
8750*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8751*61046927SAndroid Build Coastguard Worker     return g.DragDropActive ? &g.DragDropPayload : NULL;
8752*61046927SAndroid Build Coastguard Worker }
8753*61046927SAndroid Build Coastguard Worker 
8754*61046927SAndroid Build Coastguard Worker // We don't really use/need this now, but added it for the sake of consistency and because we might need it later.
EndDragDropTarget()8755*61046927SAndroid Build Coastguard Worker void ImGui::EndDragDropTarget()
8756*61046927SAndroid Build Coastguard Worker {
8757*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8758*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropActive);
8759*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.DragDropWithinSourceOrTarget);
8760*61046927SAndroid Build Coastguard Worker     g.DragDropWithinSourceOrTarget = false;
8761*61046927SAndroid Build Coastguard Worker }
8762*61046927SAndroid Build Coastguard Worker 
8763*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8764*61046927SAndroid Build Coastguard Worker // [SECTION] DOCKING
8765*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8766*61046927SAndroid Build Coastguard Worker 
8767*61046927SAndroid Build Coastguard Worker // (this section is filled in the 'docking' branch)
8768*61046927SAndroid Build Coastguard Worker 
8769*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8770*61046927SAndroid Build Coastguard Worker // [SECTION] LOGGING/CAPTURING
8771*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8772*61046927SAndroid Build Coastguard Worker // All text output from the interface can be captured into tty/file/clipboard.
8773*61046927SAndroid Build Coastguard Worker // By default, tree nodes are automatically opened during logging.
8774*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8775*61046927SAndroid Build Coastguard Worker 
8776*61046927SAndroid Build Coastguard Worker // Pass text data straight to log (without being displayed)
LogText(const char * fmt,...)8777*61046927SAndroid Build Coastguard Worker void ImGui::LogText(const char* fmt, ...)
8778*61046927SAndroid Build Coastguard Worker {
8779*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8780*61046927SAndroid Build Coastguard Worker     if (!g.LogEnabled)
8781*61046927SAndroid Build Coastguard Worker         return;
8782*61046927SAndroid Build Coastguard Worker 
8783*61046927SAndroid Build Coastguard Worker     va_list args;
8784*61046927SAndroid Build Coastguard Worker     va_start(args, fmt);
8785*61046927SAndroid Build Coastguard Worker     if (g.LogFile)
8786*61046927SAndroid Build Coastguard Worker         vfprintf(g.LogFile, fmt, args);
8787*61046927SAndroid Build Coastguard Worker     else
8788*61046927SAndroid Build Coastguard Worker         g.LogClipboard.appendfv(fmt, args);
8789*61046927SAndroid Build Coastguard Worker     va_end(args);
8790*61046927SAndroid Build Coastguard Worker }
8791*61046927SAndroid Build Coastguard Worker 
8792*61046927SAndroid Build Coastguard Worker // Internal version that takes a position to decide on newline placement and pad items according to their depth.
8793*61046927SAndroid Build Coastguard Worker // We split text into individual lines to add current tree level padding
LogRenderedText(const ImVec2 * ref_pos,const char * text,const char * text_end)8794*61046927SAndroid Build Coastguard Worker void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
8795*61046927SAndroid Build Coastguard Worker {
8796*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8797*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8798*61046927SAndroid Build Coastguard Worker 
8799*61046927SAndroid Build Coastguard Worker     if (!text_end)
8800*61046927SAndroid Build Coastguard Worker         text_end = FindRenderedTextEnd(text, text_end);
8801*61046927SAndroid Build Coastguard Worker 
8802*61046927SAndroid Build Coastguard Worker     const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1);
8803*61046927SAndroid Build Coastguard Worker     if (ref_pos)
8804*61046927SAndroid Build Coastguard Worker         window->DC.LogLinePosY = ref_pos->y;
8805*61046927SAndroid Build Coastguard Worker 
8806*61046927SAndroid Build Coastguard Worker     const char* text_remaining = text;
8807*61046927SAndroid Build Coastguard Worker     if (g.LogStartDepth > window->DC.TreeDepth)  // Re-adjust padding if we have popped out of our starting depth
8808*61046927SAndroid Build Coastguard Worker         g.LogStartDepth = window->DC.TreeDepth;
8809*61046927SAndroid Build Coastguard Worker     const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
8810*61046927SAndroid Build Coastguard Worker     for (;;)
8811*61046927SAndroid Build Coastguard Worker     {
8812*61046927SAndroid Build Coastguard Worker         // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
8813*61046927SAndroid Build Coastguard Worker         const char* line_start = text_remaining;
8814*61046927SAndroid Build Coastguard Worker         const char* line_end = ImStreolRange(line_start, text_end);
8815*61046927SAndroid Build Coastguard Worker         const bool is_first_line = (line_start == text);
8816*61046927SAndroid Build Coastguard Worker         const bool is_last_line = (line_end == text_end);
8817*61046927SAndroid Build Coastguard Worker         if (!is_last_line || (line_start != line_end))
8818*61046927SAndroid Build Coastguard Worker         {
8819*61046927SAndroid Build Coastguard Worker             const int char_count = (int)(line_end - line_start);
8820*61046927SAndroid Build Coastguard Worker             if (log_new_line || !is_first_line)
8821*61046927SAndroid Build Coastguard Worker                 LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start);
8822*61046927SAndroid Build Coastguard Worker             else
8823*61046927SAndroid Build Coastguard Worker                 LogText(" %.*s", char_count, line_start);
8824*61046927SAndroid Build Coastguard Worker         }
8825*61046927SAndroid Build Coastguard Worker 
8826*61046927SAndroid Build Coastguard Worker         if (is_last_line)
8827*61046927SAndroid Build Coastguard Worker             break;
8828*61046927SAndroid Build Coastguard Worker         text_remaining = line_end + 1;
8829*61046927SAndroid Build Coastguard Worker     }
8830*61046927SAndroid Build Coastguard Worker }
8831*61046927SAndroid Build Coastguard Worker 
8832*61046927SAndroid Build Coastguard Worker // Start logging ImGui output to TTY
LogToTTY(int max_depth)8833*61046927SAndroid Build Coastguard Worker void ImGui::LogToTTY(int max_depth)
8834*61046927SAndroid Build Coastguard Worker {
8835*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8836*61046927SAndroid Build Coastguard Worker     if (g.LogEnabled)
8837*61046927SAndroid Build Coastguard Worker         return;
8838*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8839*61046927SAndroid Build Coastguard Worker 
8840*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.LogFile == NULL);
8841*61046927SAndroid Build Coastguard Worker     g.LogFile = stdout;
8842*61046927SAndroid Build Coastguard Worker     g.LogEnabled = true;
8843*61046927SAndroid Build Coastguard Worker     g.LogStartDepth = window->DC.TreeDepth;
8844*61046927SAndroid Build Coastguard Worker     if (max_depth >= 0)
8845*61046927SAndroid Build Coastguard Worker         g.LogAutoExpandMaxDepth = max_depth;
8846*61046927SAndroid Build Coastguard Worker }
8847*61046927SAndroid Build Coastguard Worker 
8848*61046927SAndroid Build Coastguard Worker // Start logging ImGui output to given file
LogToFile(int max_depth,const char * filename)8849*61046927SAndroid Build Coastguard Worker void ImGui::LogToFile(int max_depth, const char* filename)
8850*61046927SAndroid Build Coastguard Worker {
8851*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8852*61046927SAndroid Build Coastguard Worker     if (g.LogEnabled)
8853*61046927SAndroid Build Coastguard Worker         return;
8854*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8855*61046927SAndroid Build Coastguard Worker 
8856*61046927SAndroid Build Coastguard Worker     if (!filename)
8857*61046927SAndroid Build Coastguard Worker     {
8858*61046927SAndroid Build Coastguard Worker         filename = g.IO.LogFilename;
8859*61046927SAndroid Build Coastguard Worker         if (!filename)
8860*61046927SAndroid Build Coastguard Worker             return;
8861*61046927SAndroid Build Coastguard Worker     }
8862*61046927SAndroid Build Coastguard Worker 
8863*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.LogFile == NULL);
8864*61046927SAndroid Build Coastguard Worker     g.LogFile = ImFileOpen(filename, "ab");
8865*61046927SAndroid Build Coastguard Worker     if (!g.LogFile)
8866*61046927SAndroid Build Coastguard Worker     {
8867*61046927SAndroid Build Coastguard Worker         IM_ASSERT(0);
8868*61046927SAndroid Build Coastguard Worker         return;
8869*61046927SAndroid Build Coastguard Worker     }
8870*61046927SAndroid Build Coastguard Worker     g.LogEnabled = true;
8871*61046927SAndroid Build Coastguard Worker     g.LogStartDepth = window->DC.TreeDepth;
8872*61046927SAndroid Build Coastguard Worker     if (max_depth >= 0)
8873*61046927SAndroid Build Coastguard Worker         g.LogAutoExpandMaxDepth = max_depth;
8874*61046927SAndroid Build Coastguard Worker }
8875*61046927SAndroid Build Coastguard Worker 
8876*61046927SAndroid Build Coastguard Worker // Start logging ImGui output to clipboard
LogToClipboard(int max_depth)8877*61046927SAndroid Build Coastguard Worker void ImGui::LogToClipboard(int max_depth)
8878*61046927SAndroid Build Coastguard Worker {
8879*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8880*61046927SAndroid Build Coastguard Worker     if (g.LogEnabled)
8881*61046927SAndroid Build Coastguard Worker         return;
8882*61046927SAndroid Build Coastguard Worker     ImGuiWindow* window = g.CurrentWindow;
8883*61046927SAndroid Build Coastguard Worker 
8884*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.LogFile == NULL);
8885*61046927SAndroid Build Coastguard Worker     g.LogFile = NULL;
8886*61046927SAndroid Build Coastguard Worker     g.LogEnabled = true;
8887*61046927SAndroid Build Coastguard Worker     g.LogStartDepth = window->DC.TreeDepth;
8888*61046927SAndroid Build Coastguard Worker     if (max_depth >= 0)
8889*61046927SAndroid Build Coastguard Worker         g.LogAutoExpandMaxDepth = max_depth;
8890*61046927SAndroid Build Coastguard Worker }
8891*61046927SAndroid Build Coastguard Worker 
LogFinish()8892*61046927SAndroid Build Coastguard Worker void ImGui::LogFinish()
8893*61046927SAndroid Build Coastguard Worker {
8894*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8895*61046927SAndroid Build Coastguard Worker     if (!g.LogEnabled)
8896*61046927SAndroid Build Coastguard Worker         return;
8897*61046927SAndroid Build Coastguard Worker 
8898*61046927SAndroid Build Coastguard Worker     LogText(IM_NEWLINE);
8899*61046927SAndroid Build Coastguard Worker     if (g.LogFile != NULL)
8900*61046927SAndroid Build Coastguard Worker     {
8901*61046927SAndroid Build Coastguard Worker         if (g.LogFile == stdout)
8902*61046927SAndroid Build Coastguard Worker             fflush(g.LogFile);
8903*61046927SAndroid Build Coastguard Worker         else
8904*61046927SAndroid Build Coastguard Worker             fclose(g.LogFile);
8905*61046927SAndroid Build Coastguard Worker         g.LogFile = NULL;
8906*61046927SAndroid Build Coastguard Worker     }
8907*61046927SAndroid Build Coastguard Worker     if (g.LogClipboard.size() > 1)
8908*61046927SAndroid Build Coastguard Worker     {
8909*61046927SAndroid Build Coastguard Worker         SetClipboardText(g.LogClipboard.begin());
8910*61046927SAndroid Build Coastguard Worker         g.LogClipboard.clear();
8911*61046927SAndroid Build Coastguard Worker     }
8912*61046927SAndroid Build Coastguard Worker     g.LogEnabled = false;
8913*61046927SAndroid Build Coastguard Worker }
8914*61046927SAndroid Build Coastguard Worker 
8915*61046927SAndroid Build Coastguard Worker // Helper to display logging buttons
LogButtons()8916*61046927SAndroid Build Coastguard Worker void ImGui::LogButtons()
8917*61046927SAndroid Build Coastguard Worker {
8918*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8919*61046927SAndroid Build Coastguard Worker 
8920*61046927SAndroid Build Coastguard Worker     PushID("LogButtons");
8921*61046927SAndroid Build Coastguard Worker     const bool log_to_tty = Button("Log To TTY"); SameLine();
8922*61046927SAndroid Build Coastguard Worker     const bool log_to_file = Button("Log To File"); SameLine();
8923*61046927SAndroid Build Coastguard Worker     const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
8924*61046927SAndroid Build Coastguard Worker     PushItemWidth(80.0f);
8925*61046927SAndroid Build Coastguard Worker     PushAllowKeyboardFocus(false);
8926*61046927SAndroid Build Coastguard Worker     SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL);
8927*61046927SAndroid Build Coastguard Worker     PopAllowKeyboardFocus();
8928*61046927SAndroid Build Coastguard Worker     PopItemWidth();
8929*61046927SAndroid Build Coastguard Worker     PopID();
8930*61046927SAndroid Build Coastguard Worker 
8931*61046927SAndroid Build Coastguard Worker     // Start logging at the end of the function so that the buttons don't appear in the log
8932*61046927SAndroid Build Coastguard Worker     if (log_to_tty)
8933*61046927SAndroid Build Coastguard Worker         LogToTTY(g.LogAutoExpandMaxDepth);
8934*61046927SAndroid Build Coastguard Worker     if (log_to_file)
8935*61046927SAndroid Build Coastguard Worker         LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename);
8936*61046927SAndroid Build Coastguard Worker     if (log_to_clipboard)
8937*61046927SAndroid Build Coastguard Worker         LogToClipboard(g.LogAutoExpandMaxDepth);
8938*61046927SAndroid Build Coastguard Worker }
8939*61046927SAndroid Build Coastguard Worker 
8940*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8941*61046927SAndroid Build Coastguard Worker // [SECTION] SETTINGS
8942*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
8943*61046927SAndroid Build Coastguard Worker 
MarkIniSettingsDirty()8944*61046927SAndroid Build Coastguard Worker void ImGui::MarkIniSettingsDirty()
8945*61046927SAndroid Build Coastguard Worker {
8946*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8947*61046927SAndroid Build Coastguard Worker     if (g.SettingsDirtyTimer <= 0.0f)
8948*61046927SAndroid Build Coastguard Worker         g.SettingsDirtyTimer = g.IO.IniSavingRate;
8949*61046927SAndroid Build Coastguard Worker }
8950*61046927SAndroid Build Coastguard Worker 
MarkIniSettingsDirty(ImGuiWindow * window)8951*61046927SAndroid Build Coastguard Worker void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
8952*61046927SAndroid Build Coastguard Worker {
8953*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8954*61046927SAndroid Build Coastguard Worker     if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
8955*61046927SAndroid Build Coastguard Worker         if (g.SettingsDirtyTimer <= 0.0f)
8956*61046927SAndroid Build Coastguard Worker             g.SettingsDirtyTimer = g.IO.IniSavingRate;
8957*61046927SAndroid Build Coastguard Worker }
8958*61046927SAndroid Build Coastguard Worker 
CreateNewWindowSettings(const char * name)8959*61046927SAndroid Build Coastguard Worker ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
8960*61046927SAndroid Build Coastguard Worker {
8961*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8962*61046927SAndroid Build Coastguard Worker     g.SettingsWindows.push_back(ImGuiWindowSettings());
8963*61046927SAndroid Build Coastguard Worker     ImGuiWindowSettings* settings = &g.SettingsWindows.back();
8964*61046927SAndroid Build Coastguard Worker     settings->Name = ImStrdup(name);
8965*61046927SAndroid Build Coastguard Worker     settings->ID = ImHashStr(name, 0);
8966*61046927SAndroid Build Coastguard Worker     return settings;
8967*61046927SAndroid Build Coastguard Worker }
8968*61046927SAndroid Build Coastguard Worker 
FindWindowSettings(ImGuiID id)8969*61046927SAndroid Build Coastguard Worker ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id)
8970*61046927SAndroid Build Coastguard Worker {
8971*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8972*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != g.SettingsWindows.Size; i++)
8973*61046927SAndroid Build Coastguard Worker         if (g.SettingsWindows[i].ID == id)
8974*61046927SAndroid Build Coastguard Worker             return &g.SettingsWindows[i];
8975*61046927SAndroid Build Coastguard Worker     return NULL;
8976*61046927SAndroid Build Coastguard Worker }
8977*61046927SAndroid Build Coastguard Worker 
FindOrCreateWindowSettings(const char * name)8978*61046927SAndroid Build Coastguard Worker ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name)
8979*61046927SAndroid Build Coastguard Worker {
8980*61046927SAndroid Build Coastguard Worker     if (ImGuiWindowSettings* settings = FindWindowSettings(ImHashStr(name, 0)))
8981*61046927SAndroid Build Coastguard Worker         return settings;
8982*61046927SAndroid Build Coastguard Worker     return CreateNewWindowSettings(name);
8983*61046927SAndroid Build Coastguard Worker }
8984*61046927SAndroid Build Coastguard Worker 
LoadIniSettingsFromDisk(const char * ini_filename)8985*61046927SAndroid Build Coastguard Worker void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
8986*61046927SAndroid Build Coastguard Worker {
8987*61046927SAndroid Build Coastguard Worker     size_t file_data_size = 0;
8988*61046927SAndroid Build Coastguard Worker     char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size);
8989*61046927SAndroid Build Coastguard Worker     if (!file_data)
8990*61046927SAndroid Build Coastguard Worker         return;
8991*61046927SAndroid Build Coastguard Worker     LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
8992*61046927SAndroid Build Coastguard Worker     ImGui::MemFree(file_data);
8993*61046927SAndroid Build Coastguard Worker }
8994*61046927SAndroid Build Coastguard Worker 
FindSettingsHandler(const char * type_name)8995*61046927SAndroid Build Coastguard Worker ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
8996*61046927SAndroid Build Coastguard Worker {
8997*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
8998*61046927SAndroid Build Coastguard Worker     const ImGuiID type_hash = ImHashStr(type_name, 0);
8999*61046927SAndroid Build Coastguard Worker     for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
9000*61046927SAndroid Build Coastguard Worker         if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
9001*61046927SAndroid Build Coastguard Worker             return &g.SettingsHandlers[handler_n];
9002*61046927SAndroid Build Coastguard Worker     return NULL;
9003*61046927SAndroid Build Coastguard Worker }
9004*61046927SAndroid Build Coastguard Worker 
9005*61046927SAndroid Build Coastguard Worker // Zero-tolerance, no error reporting, cheap .ini parsing
LoadIniSettingsFromMemory(const char * ini_data,size_t ini_size)9006*61046927SAndroid Build Coastguard Worker void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
9007*61046927SAndroid Build Coastguard Worker {
9008*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9009*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.Initialized);
9010*61046927SAndroid Build Coastguard Worker     IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0);
9011*61046927SAndroid Build Coastguard Worker 
9012*61046927SAndroid Build Coastguard Worker     // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
9013*61046927SAndroid Build Coastguard Worker     // 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..
9014*61046927SAndroid Build Coastguard Worker     if (ini_size == 0)
9015*61046927SAndroid Build Coastguard Worker         ini_size = strlen(ini_data);
9016*61046927SAndroid Build Coastguard Worker     char* buf = (char*)ImGui::MemAlloc(ini_size + 1);
9017*61046927SAndroid Build Coastguard Worker     char* buf_end = buf + ini_size;
9018*61046927SAndroid Build Coastguard Worker     memcpy(buf, ini_data, ini_size);
9019*61046927SAndroid Build Coastguard Worker     buf[ini_size] = 0;
9020*61046927SAndroid Build Coastguard Worker 
9021*61046927SAndroid Build Coastguard Worker     void* entry_data = NULL;
9022*61046927SAndroid Build Coastguard Worker     ImGuiSettingsHandler* entry_handler = NULL;
9023*61046927SAndroid Build Coastguard Worker 
9024*61046927SAndroid Build Coastguard Worker     char* line_end = NULL;
9025*61046927SAndroid Build Coastguard Worker     for (char* line = buf; line < buf_end; line = line_end + 1)
9026*61046927SAndroid Build Coastguard Worker     {
9027*61046927SAndroid Build Coastguard Worker         // Skip new lines markers, then find end of the line
9028*61046927SAndroid Build Coastguard Worker         while (*line == '\n' || *line == '\r')
9029*61046927SAndroid Build Coastguard Worker             line++;
9030*61046927SAndroid Build Coastguard Worker         line_end = line;
9031*61046927SAndroid Build Coastguard Worker         while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
9032*61046927SAndroid Build Coastguard Worker             line_end++;
9033*61046927SAndroid Build Coastguard Worker         line_end[0] = 0;
9034*61046927SAndroid Build Coastguard Worker         if (line[0] == ';')
9035*61046927SAndroid Build Coastguard Worker             continue;
9036*61046927SAndroid Build Coastguard Worker         if (line[0] == '[' && line_end > line && line_end[-1] == ']')
9037*61046927SAndroid Build Coastguard Worker         {
9038*61046927SAndroid Build Coastguard Worker             // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
9039*61046927SAndroid Build Coastguard Worker             line_end[-1] = 0;
9040*61046927SAndroid Build Coastguard Worker             const char* name_end = line_end - 1;
9041*61046927SAndroid Build Coastguard Worker             const char* type_start = line + 1;
9042*61046927SAndroid Build Coastguard Worker             char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']');
9043*61046927SAndroid Build Coastguard Worker             const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
9044*61046927SAndroid Build Coastguard Worker             if (!type_end || !name_start)
9045*61046927SAndroid Build Coastguard Worker             {
9046*61046927SAndroid Build Coastguard Worker                 name_start = type_start; // Import legacy entries that have no type
9047*61046927SAndroid Build Coastguard Worker                 type_start = "Window";
9048*61046927SAndroid Build Coastguard Worker             }
9049*61046927SAndroid Build Coastguard Worker             else
9050*61046927SAndroid Build Coastguard Worker             {
9051*61046927SAndroid Build Coastguard Worker                 *type_end = 0; // Overwrite first ']'
9052*61046927SAndroid Build Coastguard Worker                 name_start++;  // Skip second '['
9053*61046927SAndroid Build Coastguard Worker             }
9054*61046927SAndroid Build Coastguard Worker             entry_handler = FindSettingsHandler(type_start);
9055*61046927SAndroid Build Coastguard Worker             entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL;
9056*61046927SAndroid Build Coastguard Worker         }
9057*61046927SAndroid Build Coastguard Worker         else if (entry_handler != NULL && entry_data != NULL)
9058*61046927SAndroid Build Coastguard Worker         {
9059*61046927SAndroid Build Coastguard Worker             // Let type handler parse the line
9060*61046927SAndroid Build Coastguard Worker             entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
9061*61046927SAndroid Build Coastguard Worker         }
9062*61046927SAndroid Build Coastguard Worker     }
9063*61046927SAndroid Build Coastguard Worker     ImGui::MemFree(buf);
9064*61046927SAndroid Build Coastguard Worker     g.SettingsLoaded = true;
9065*61046927SAndroid Build Coastguard Worker }
9066*61046927SAndroid Build Coastguard Worker 
SaveIniSettingsToDisk(const char * ini_filename)9067*61046927SAndroid Build Coastguard Worker void ImGui::SaveIniSettingsToDisk(const char* ini_filename)
9068*61046927SAndroid Build Coastguard Worker {
9069*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9070*61046927SAndroid Build Coastguard Worker     g.SettingsDirtyTimer = 0.0f;
9071*61046927SAndroid Build Coastguard Worker     if (!ini_filename)
9072*61046927SAndroid Build Coastguard Worker         return;
9073*61046927SAndroid Build Coastguard Worker 
9074*61046927SAndroid Build Coastguard Worker     size_t ini_data_size = 0;
9075*61046927SAndroid Build Coastguard Worker     const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
9076*61046927SAndroid Build Coastguard Worker     FILE* f = ImFileOpen(ini_filename, "wt");
9077*61046927SAndroid Build Coastguard Worker     if (!f)
9078*61046927SAndroid Build Coastguard Worker         return;
9079*61046927SAndroid Build Coastguard Worker     fwrite(ini_data, sizeof(char), ini_data_size, f);
9080*61046927SAndroid Build Coastguard Worker     fclose(f);
9081*61046927SAndroid Build Coastguard Worker }
9082*61046927SAndroid Build Coastguard Worker 
9083*61046927SAndroid Build Coastguard Worker // Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
SaveIniSettingsToMemory(size_t * out_size)9084*61046927SAndroid Build Coastguard Worker const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
9085*61046927SAndroid Build Coastguard Worker {
9086*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9087*61046927SAndroid Build Coastguard Worker     g.SettingsDirtyTimer = 0.0f;
9088*61046927SAndroid Build Coastguard Worker     g.SettingsIniData.Buf.resize(0);
9089*61046927SAndroid Build Coastguard Worker     g.SettingsIniData.Buf.push_back(0);
9090*61046927SAndroid Build Coastguard Worker     for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
9091*61046927SAndroid Build Coastguard Worker     {
9092*61046927SAndroid Build Coastguard Worker         ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n];
9093*61046927SAndroid Build Coastguard Worker         handler->WriteAllFn(&g, handler, &g.SettingsIniData);
9094*61046927SAndroid Build Coastguard Worker     }
9095*61046927SAndroid Build Coastguard Worker     if (out_size)
9096*61046927SAndroid Build Coastguard Worker         *out_size = (size_t)g.SettingsIniData.size();
9097*61046927SAndroid Build Coastguard Worker     return g.SettingsIniData.c_str();
9098*61046927SAndroid Build Coastguard Worker }
9099*61046927SAndroid Build Coastguard Worker 
SettingsHandlerWindow_ReadOpen(ImGuiContext *,ImGuiSettingsHandler *,const char * name)9100*61046927SAndroid Build Coastguard Worker static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
9101*61046927SAndroid Build Coastguard Worker {
9102*61046927SAndroid Build Coastguard Worker     ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHashStr(name, 0));
9103*61046927SAndroid Build Coastguard Worker     if (!settings)
9104*61046927SAndroid Build Coastguard Worker         settings = ImGui::CreateNewWindowSettings(name);
9105*61046927SAndroid Build Coastguard Worker     return (void*)settings;
9106*61046927SAndroid Build Coastguard Worker }
9107*61046927SAndroid Build Coastguard Worker 
SettingsHandlerWindow_ReadLine(ImGuiContext *,ImGuiSettingsHandler *,void * entry,const char * line)9108*61046927SAndroid Build Coastguard Worker static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
9109*61046927SAndroid Build Coastguard Worker {
9110*61046927SAndroid Build Coastguard Worker     ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
9111*61046927SAndroid Build Coastguard Worker     float x, y;
9112*61046927SAndroid Build Coastguard Worker     int i;
9113*61046927SAndroid Build Coastguard Worker     if (sscanf(line, "Pos=%f,%f", &x, &y) == 2)         settings->Pos = ImVec2(x, y);
9114*61046927SAndroid Build Coastguard Worker     else if (sscanf(line, "Size=%f,%f", &x, &y) == 2)   settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize);
9115*61046927SAndroid Build Coastguard Worker     else if (sscanf(line, "Collapsed=%d", &i) == 1)     settings->Collapsed = (i != 0);
9116*61046927SAndroid Build Coastguard Worker }
9117*61046927SAndroid Build Coastguard Worker 
SettingsHandlerWindow_WriteAll(ImGuiContext * imgui_ctx,ImGuiSettingsHandler * handler,ImGuiTextBuffer * buf)9118*61046927SAndroid Build Coastguard Worker static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
9119*61046927SAndroid Build Coastguard Worker {
9120*61046927SAndroid Build Coastguard Worker     // Gather data from windows that were active during this session
9121*61046927SAndroid Build Coastguard Worker     // (if a window wasn't opened in this session we preserve its settings)
9122*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *imgui_ctx;
9123*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != g.Windows.Size; i++)
9124*61046927SAndroid Build Coastguard Worker     {
9125*61046927SAndroid Build Coastguard Worker         ImGuiWindow* window = g.Windows[i];
9126*61046927SAndroid Build Coastguard Worker         if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
9127*61046927SAndroid Build Coastguard Worker             continue;
9128*61046927SAndroid Build Coastguard Worker 
9129*61046927SAndroid Build Coastguard Worker         ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID);
9130*61046927SAndroid Build Coastguard Worker         if (!settings)
9131*61046927SAndroid Build Coastguard Worker         {
9132*61046927SAndroid Build Coastguard Worker             settings = ImGui::CreateNewWindowSettings(window->Name);
9133*61046927SAndroid Build Coastguard Worker             window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
9134*61046927SAndroid Build Coastguard Worker         }
9135*61046927SAndroid Build Coastguard Worker         IM_ASSERT(settings->ID == window->ID);
9136*61046927SAndroid Build Coastguard Worker         settings->Pos = window->Pos;
9137*61046927SAndroid Build Coastguard Worker         settings->Size = window->SizeFull;
9138*61046927SAndroid Build Coastguard Worker         settings->Collapsed = window->Collapsed;
9139*61046927SAndroid Build Coastguard Worker     }
9140*61046927SAndroid Build Coastguard Worker 
9141*61046927SAndroid Build Coastguard Worker     // Write to text buffer
9142*61046927SAndroid Build Coastguard Worker     buf->reserve(buf->size() + g.SettingsWindows.Size * 96); // ballpark reserve
9143*61046927SAndroid Build Coastguard Worker     for (int i = 0; i != g.SettingsWindows.Size; i++)
9144*61046927SAndroid Build Coastguard Worker     {
9145*61046927SAndroid Build Coastguard Worker         const ImGuiWindowSettings* settings = &g.SettingsWindows[i];
9146*61046927SAndroid Build Coastguard Worker         if (settings->Pos.x == FLT_MAX)
9147*61046927SAndroid Build Coastguard Worker             continue;
9148*61046927SAndroid Build Coastguard Worker         const char* name = settings->Name;
9149*61046927SAndroid Build Coastguard Worker         if (const char* p = strstr(name, "###"))  // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
9150*61046927SAndroid Build Coastguard Worker             name = p;
9151*61046927SAndroid Build Coastguard Worker         buf->appendf("[%s][%s]\n", handler->TypeName, name);
9152*61046927SAndroid Build Coastguard Worker         buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
9153*61046927SAndroid Build Coastguard Worker         buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
9154*61046927SAndroid Build Coastguard Worker         buf->appendf("Collapsed=%d\n", settings->Collapsed);
9155*61046927SAndroid Build Coastguard Worker         buf->appendf("\n");
9156*61046927SAndroid Build Coastguard Worker     }
9157*61046927SAndroid Build Coastguard Worker }
9158*61046927SAndroid Build Coastguard Worker 
9159*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9160*61046927SAndroid Build Coastguard Worker // [SECTION] PLATFORM DEPENDENT HELPERS
9161*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9162*61046927SAndroid Build Coastguard Worker 
9163*61046927SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(_WINDOWS_) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS))
9164*61046927SAndroid Build Coastguard Worker #ifndef WIN32_LEAN_AND_MEAN
9165*61046927SAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
9166*61046927SAndroid Build Coastguard Worker #endif
9167*61046927SAndroid Build Coastguard Worker #ifndef __MINGW32__
9168*61046927SAndroid Build Coastguard Worker #include <Windows.h>
9169*61046927SAndroid Build Coastguard Worker #else
9170*61046927SAndroid Build Coastguard Worker #include <windows.h>
9171*61046927SAndroid Build Coastguard Worker #endif
9172*61046927SAndroid Build Coastguard Worker #endif
9173*61046927SAndroid Build Coastguard Worker 
9174*61046927SAndroid Build Coastguard Worker // Win32 API clipboard implementation
9175*61046927SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
9176*61046927SAndroid Build Coastguard Worker 
9177*61046927SAndroid Build Coastguard Worker #ifdef _MSC_VER
9178*61046927SAndroid Build Coastguard Worker #pragma comment(lib, "user32")
9179*61046927SAndroid Build Coastguard Worker #endif
9180*61046927SAndroid Build Coastguard Worker 
GetClipboardTextFn_DefaultImpl(void *)9181*61046927SAndroid Build Coastguard Worker static const char* GetClipboardTextFn_DefaultImpl(void*)
9182*61046927SAndroid Build Coastguard Worker {
9183*61046927SAndroid Build Coastguard Worker     static ImVector<char> buf_local;
9184*61046927SAndroid Build Coastguard Worker     buf_local.clear();
9185*61046927SAndroid Build Coastguard Worker     if (!::OpenClipboard(NULL))
9186*61046927SAndroid Build Coastguard Worker         return NULL;
9187*61046927SAndroid Build Coastguard Worker     HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
9188*61046927SAndroid Build Coastguard Worker     if (wbuf_handle == NULL)
9189*61046927SAndroid Build Coastguard Worker     {
9190*61046927SAndroid Build Coastguard Worker         ::CloseClipboard();
9191*61046927SAndroid Build Coastguard Worker         return NULL;
9192*61046927SAndroid Build Coastguard Worker     }
9193*61046927SAndroid Build Coastguard Worker     if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle))
9194*61046927SAndroid Build Coastguard Worker     {
9195*61046927SAndroid Build Coastguard Worker         int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
9196*61046927SAndroid Build Coastguard Worker         buf_local.resize(buf_len);
9197*61046927SAndroid Build Coastguard Worker         ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);
9198*61046927SAndroid Build Coastguard Worker     }
9199*61046927SAndroid Build Coastguard Worker     ::GlobalUnlock(wbuf_handle);
9200*61046927SAndroid Build Coastguard Worker     ::CloseClipboard();
9201*61046927SAndroid Build Coastguard Worker     return buf_local.Data;
9202*61046927SAndroid Build Coastguard Worker }
9203*61046927SAndroid Build Coastguard Worker 
SetClipboardTextFn_DefaultImpl(void *,const char * text)9204*61046927SAndroid Build Coastguard Worker static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
9205*61046927SAndroid Build Coastguard Worker {
9206*61046927SAndroid Build Coastguard Worker     if (!::OpenClipboard(NULL))
9207*61046927SAndroid Build Coastguard Worker         return;
9208*61046927SAndroid Build Coastguard Worker     const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
9209*61046927SAndroid Build Coastguard Worker     HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
9210*61046927SAndroid Build Coastguard Worker     if (wbuf_handle == NULL)
9211*61046927SAndroid Build Coastguard Worker     {
9212*61046927SAndroid Build Coastguard Worker         ::CloseClipboard();
9213*61046927SAndroid Build Coastguard Worker         return;
9214*61046927SAndroid Build Coastguard Worker     }
9215*61046927SAndroid Build Coastguard Worker     ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle);
9216*61046927SAndroid Build Coastguard Worker     ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
9217*61046927SAndroid Build Coastguard Worker     ::GlobalUnlock(wbuf_handle);
9218*61046927SAndroid Build Coastguard Worker     ::EmptyClipboard();
9219*61046927SAndroid Build Coastguard Worker     if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
9220*61046927SAndroid Build Coastguard Worker         ::GlobalFree(wbuf_handle);
9221*61046927SAndroid Build Coastguard Worker     ::CloseClipboard();
9222*61046927SAndroid Build Coastguard Worker }
9223*61046927SAndroid Build Coastguard Worker 
9224*61046927SAndroid Build Coastguard Worker #else
9225*61046927SAndroid Build Coastguard Worker 
9226*61046927SAndroid Build Coastguard Worker // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
GetClipboardTextFn_DefaultImpl(void *)9227*61046927SAndroid Build Coastguard Worker static const char* GetClipboardTextFn_DefaultImpl(void*)
9228*61046927SAndroid Build Coastguard Worker {
9229*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9230*61046927SAndroid Build Coastguard Worker     return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin();
9231*61046927SAndroid Build Coastguard Worker }
9232*61046927SAndroid Build Coastguard Worker 
9233*61046927SAndroid Build Coastguard Worker // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
SetClipboardTextFn_DefaultImpl(void *,const char * text)9234*61046927SAndroid Build Coastguard Worker static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
9235*61046927SAndroid Build Coastguard Worker {
9236*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9237*61046927SAndroid Build Coastguard Worker     g.PrivateClipboard.clear();
9238*61046927SAndroid Build Coastguard Worker     const char* text_end = text + strlen(text);
9239*61046927SAndroid Build Coastguard Worker     g.PrivateClipboard.resize((int)(text_end - text) + 1);
9240*61046927SAndroid Build Coastguard Worker     memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text));
9241*61046927SAndroid Build Coastguard Worker     g.PrivateClipboard[(int)(text_end - text)] = 0;
9242*61046927SAndroid Build Coastguard Worker }
9243*61046927SAndroid Build Coastguard Worker 
9244*61046927SAndroid Build Coastguard Worker #endif
9245*61046927SAndroid Build Coastguard Worker 
9246*61046927SAndroid Build Coastguard Worker // Win32 API IME support (for Asian languages, etc.)
9247*61046927SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
9248*61046927SAndroid Build Coastguard Worker 
9249*61046927SAndroid Build Coastguard Worker #include <imm.h>
9250*61046927SAndroid Build Coastguard Worker #ifdef _MSC_VER
9251*61046927SAndroid Build Coastguard Worker #pragma comment(lib, "imm32")
9252*61046927SAndroid Build Coastguard Worker #endif
9253*61046927SAndroid Build Coastguard Worker 
ImeSetInputScreenPosFn_DefaultImpl(int x,int y)9254*61046927SAndroid Build Coastguard Worker static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
9255*61046927SAndroid Build Coastguard Worker {
9256*61046927SAndroid Build Coastguard Worker     // Notify OS Input Method Editor of text input position
9257*61046927SAndroid Build Coastguard Worker     if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)
9258*61046927SAndroid Build Coastguard Worker         if (HIMC himc = ::ImmGetContext(hwnd))
9259*61046927SAndroid Build Coastguard Worker         {
9260*61046927SAndroid Build Coastguard Worker             COMPOSITIONFORM cf;
9261*61046927SAndroid Build Coastguard Worker             cf.ptCurrentPos.x = x;
9262*61046927SAndroid Build Coastguard Worker             cf.ptCurrentPos.y = y;
9263*61046927SAndroid Build Coastguard Worker             cf.dwStyle = CFS_FORCE_POSITION;
9264*61046927SAndroid Build Coastguard Worker             ::ImmSetCompositionWindow(himc, &cf);
9265*61046927SAndroid Build Coastguard Worker             ::ImmReleaseContext(hwnd, himc);
9266*61046927SAndroid Build Coastguard Worker         }
9267*61046927SAndroid Build Coastguard Worker }
9268*61046927SAndroid Build Coastguard Worker 
9269*61046927SAndroid Build Coastguard Worker #else
9270*61046927SAndroid Build Coastguard Worker 
ImeSetInputScreenPosFn_DefaultImpl(int,int)9271*61046927SAndroid Build Coastguard Worker static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
9272*61046927SAndroid Build Coastguard Worker 
9273*61046927SAndroid Build Coastguard Worker #endif
9274*61046927SAndroid Build Coastguard Worker 
9275*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9276*61046927SAndroid Build Coastguard Worker // [SECTION] METRICS/DEBUG WINDOW
9277*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9278*61046927SAndroid Build Coastguard Worker 
ShowMetricsWindow(bool * p_open)9279*61046927SAndroid Build Coastguard Worker void ImGui::ShowMetricsWindow(bool* p_open)
9280*61046927SAndroid Build Coastguard Worker {
9281*61046927SAndroid Build Coastguard Worker     if (!ImGui::Begin("ImGui Metrics", p_open))
9282*61046927SAndroid Build Coastguard Worker     {
9283*61046927SAndroid Build Coastguard Worker         ImGui::End();
9284*61046927SAndroid Build Coastguard Worker         return;
9285*61046927SAndroid Build Coastguard Worker     }
9286*61046927SAndroid Build Coastguard Worker 
9287*61046927SAndroid Build Coastguard Worker     static bool show_draw_cmd_clip_rects = true;
9288*61046927SAndroid Build Coastguard Worker     static bool show_window_begin_order = false;
9289*61046927SAndroid Build Coastguard Worker     ImGuiIO& io = ImGui::GetIO();
9290*61046927SAndroid Build Coastguard Worker     ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
9291*61046927SAndroid Build Coastguard Worker     ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
9292*61046927SAndroid Build Coastguard Worker     ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
9293*61046927SAndroid Build Coastguard Worker     ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
9294*61046927SAndroid Build Coastguard Worker     ImGui::Text("%d allocations", io.MetricsActiveAllocations);
9295*61046927SAndroid Build Coastguard Worker     ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_draw_cmd_clip_rects);
9296*61046927SAndroid Build Coastguard Worker     ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order);
9297*61046927SAndroid Build Coastguard Worker     ImGui::Separator();
9298*61046927SAndroid Build Coastguard Worker 
9299*61046927SAndroid Build Coastguard Worker     struct Funcs
9300*61046927SAndroid Build Coastguard Worker     {
9301*61046927SAndroid Build Coastguard Worker         static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label)
9302*61046927SAndroid Build Coastguard Worker         {
9303*61046927SAndroid Build Coastguard Worker             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);
9304*61046927SAndroid Build Coastguard Worker             if (draw_list == ImGui::GetWindowDrawList())
9305*61046927SAndroid Build Coastguard Worker             {
9306*61046927SAndroid Build Coastguard Worker                 ImGui::SameLine();
9307*61046927SAndroid Build Coastguard Worker                 ImGui::TextColored(ImVec4(1.0f,0.4f,0.4f,1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
9308*61046927SAndroid Build Coastguard Worker                 if (node_open) ImGui::TreePop();
9309*61046927SAndroid Build Coastguard Worker                 return;
9310*61046927SAndroid Build Coastguard Worker             }
9311*61046927SAndroid Build Coastguard Worker 
9312*61046927SAndroid Build Coastguard Worker             ImDrawList* overlay_draw_list = GetOverlayDrawList(window); // Render additional visuals into the top-most draw list
9313*61046927SAndroid Build Coastguard Worker             if (window && IsItemHovered())
9314*61046927SAndroid Build Coastguard Worker                 overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
9315*61046927SAndroid Build Coastguard Worker             if (!node_open)
9316*61046927SAndroid Build Coastguard Worker                 return;
9317*61046927SAndroid Build Coastguard Worker 
9318*61046927SAndroid Build Coastguard Worker             int elem_offset = 0;
9319*61046927SAndroid Build Coastguard Worker             for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)
9320*61046927SAndroid Build Coastguard Worker             {
9321*61046927SAndroid Build Coastguard Worker                 if (pcmd->UserCallback == NULL && pcmd->ElemCount == 0)
9322*61046927SAndroid Build Coastguard Worker                     continue;
9323*61046927SAndroid Build Coastguard Worker                 if (pcmd->UserCallback)
9324*61046927SAndroid Build Coastguard Worker                 {
9325*61046927SAndroid Build Coastguard Worker                     ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
9326*61046927SAndroid Build Coastguard Worker                     continue;
9327*61046927SAndroid Build Coastguard Worker                 }
9328*61046927SAndroid Build Coastguard Worker                 ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
9329*61046927SAndroid Build Coastguard Worker                 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);
9330*61046927SAndroid Build Coastguard Worker                 if (show_draw_cmd_clip_rects && ImGui::IsItemHovered())
9331*61046927SAndroid Build Coastguard Worker                 {
9332*61046927SAndroid Build Coastguard Worker                     ImRect clip_rect = pcmd->ClipRect;
9333*61046927SAndroid Build Coastguard Worker                     ImRect vtxs_rect;
9334*61046927SAndroid Build Coastguard Worker                     for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)
9335*61046927SAndroid Build Coastguard Worker                         vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos);
9336*61046927SAndroid Build Coastguard Worker                     clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255));
9337*61046927SAndroid Build Coastguard Worker                     vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255));
9338*61046927SAndroid Build Coastguard Worker                 }
9339*61046927SAndroid Build Coastguard Worker                 if (!pcmd_node_open)
9340*61046927SAndroid Build Coastguard Worker                     continue;
9341*61046927SAndroid Build Coastguard Worker 
9342*61046927SAndroid Build Coastguard Worker                 // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
9343*61046927SAndroid Build Coastguard Worker                 ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
9344*61046927SAndroid Build Coastguard Worker                 while (clipper.Step())
9345*61046927SAndroid Build Coastguard Worker                     for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
9346*61046927SAndroid Build Coastguard Worker                     {
9347*61046927SAndroid Build Coastguard Worker                         char buf[300];
9348*61046927SAndroid Build Coastguard Worker                         char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
9349*61046927SAndroid Build Coastguard Worker                         ImVec2 triangles_pos[3];
9350*61046927SAndroid Build Coastguard Worker                         for (int n = 0; n < 3; n++, idx_i++)
9351*61046927SAndroid Build Coastguard Worker                         {
9352*61046927SAndroid Build Coastguard Worker                             int vtx_i = idx_buffer ? idx_buffer[idx_i] : idx_i;
9353*61046927SAndroid Build Coastguard Worker                             ImDrawVert& v = draw_list->VtxBuffer[vtx_i];
9354*61046927SAndroid Build Coastguard Worker                             triangles_pos[n] = v.pos;
9355*61046927SAndroid Build Coastguard Worker                             buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
9356*61046927SAndroid Build Coastguard Worker                                 (n == 0) ? "idx" : "   ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
9357*61046927SAndroid Build Coastguard Worker                         }
9358*61046927SAndroid Build Coastguard Worker                         ImGui::Selectable(buf, false);
9359*61046927SAndroid Build Coastguard Worker                         if (ImGui::IsItemHovered())
9360*61046927SAndroid Build Coastguard Worker                         {
9361*61046927SAndroid Build Coastguard Worker                             ImDrawListFlags backup_flags = overlay_draw_list->Flags;
9362*61046927SAndroid Build Coastguard Worker                             overlay_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles.
9363*61046927SAndroid Build Coastguard Worker                             overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f);
9364*61046927SAndroid Build Coastguard Worker                             overlay_draw_list->Flags = backup_flags;
9365*61046927SAndroid Build Coastguard Worker                         }
9366*61046927SAndroid Build Coastguard Worker                     }
9367*61046927SAndroid Build Coastguard Worker                 ImGui::TreePop();
9368*61046927SAndroid Build Coastguard Worker             }
9369*61046927SAndroid Build Coastguard Worker             ImGui::TreePop();
9370*61046927SAndroid Build Coastguard Worker         }
9371*61046927SAndroid Build Coastguard Worker 
9372*61046927SAndroid Build Coastguard Worker         static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* label)
9373*61046927SAndroid Build Coastguard Worker         {
9374*61046927SAndroid Build Coastguard Worker             if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size))
9375*61046927SAndroid Build Coastguard Worker                 return;
9376*61046927SAndroid Build Coastguard Worker             for (int i = 0; i < windows.Size; i++)
9377*61046927SAndroid Build Coastguard Worker                 Funcs::NodeWindow(windows[i], "Window");
9378*61046927SAndroid Build Coastguard Worker             ImGui::TreePop();
9379*61046927SAndroid Build Coastguard Worker         }
9380*61046927SAndroid Build Coastguard Worker 
9381*61046927SAndroid Build Coastguard Worker         static void NodeWindow(ImGuiWindow* window, const char* label)
9382*61046927SAndroid Build Coastguard Worker         {
9383*61046927SAndroid Build Coastguard Worker             if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
9384*61046927SAndroid Build Coastguard Worker                 return;
9385*61046927SAndroid Build Coastguard Worker             ImGuiWindowFlags flags = window->Flags;
9386*61046927SAndroid Build Coastguard Worker             NodeDrawList(window, window->DrawList, "DrawList");
9387*61046927SAndroid Build Coastguard Worker             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);
9388*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
9389*61046927SAndroid Build Coastguard Worker                 (flags & ImGuiWindowFlags_ChildWindow)  ? "Child " : "",      (flags & ImGuiWindowFlags_Tooltip)     ? "Tooltip "   : "",  (flags & ImGuiWindowFlags_Popup) ? "Popup " : "",
9390*61046927SAndroid Build Coastguard Worker                 (flags & ImGuiWindowFlags_Modal)        ? "Modal " : "",      (flags & ImGuiWindowFlags_ChildMenu)   ? "ChildMenu " : "",  (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "",
9391*61046927SAndroid Build Coastguard Worker                 (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : "");
9392*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window));
9393*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
9394*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems);
9395*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
9396*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
9397*61046927SAndroid Build Coastguard Worker             if (!window->NavRectRel[0].IsInverted())
9398*61046927SAndroid Build Coastguard Worker                 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);
9399*61046927SAndroid Build Coastguard Worker             else
9400*61046927SAndroid Build Coastguard Worker                 ImGui::BulletText("NavRectRel[0]: <None>");
9401*61046927SAndroid Build Coastguard Worker             if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
9402*61046927SAndroid Build Coastguard Worker             if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow");
9403*61046927SAndroid Build Coastguard Worker             if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
9404*61046927SAndroid Build Coastguard Worker             if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
9405*61046927SAndroid Build Coastguard Worker             {
9406*61046927SAndroid Build Coastguard Worker                 for (int n = 0; n < window->ColumnsStorage.Size; n++)
9407*61046927SAndroid Build Coastguard Worker                 {
9408*61046927SAndroid Build Coastguard Worker                     const ImGuiColumnsSet* columns = &window->ColumnsStorage[n];
9409*61046927SAndroid Build Coastguard Worker                     if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
9410*61046927SAndroid Build Coastguard Worker                     {
9411*61046927SAndroid Build Coastguard Worker                         ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX);
9412*61046927SAndroid Build Coastguard Worker                         for (int column_n = 0; column_n < columns->Columns.Size; column_n++)
9413*61046927SAndroid Build Coastguard Worker                             ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm));
9414*61046927SAndroid Build Coastguard Worker                         ImGui::TreePop();
9415*61046927SAndroid Build Coastguard Worker                     }
9416*61046927SAndroid Build Coastguard Worker                 }
9417*61046927SAndroid Build Coastguard Worker                 ImGui::TreePop();
9418*61046927SAndroid Build Coastguard Worker             }
9419*61046927SAndroid Build Coastguard Worker             ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
9420*61046927SAndroid Build Coastguard Worker             ImGui::TreePop();
9421*61046927SAndroid Build Coastguard Worker         }
9422*61046927SAndroid Build Coastguard Worker 
9423*61046927SAndroid Build Coastguard Worker         static void NodeTabBar(ImGuiTabBar* tab_bar)
9424*61046927SAndroid Build Coastguard Worker         {
9425*61046927SAndroid Build Coastguard Worker             // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings.
9426*61046927SAndroid Build Coastguard Worker             char buf[256];
9427*61046927SAndroid Build Coastguard Worker             char* p = buf;
9428*61046927SAndroid Build Coastguard Worker             const char* buf_end = buf + IM_ARRAYSIZE(buf);
9429*61046927SAndroid Build Coastguard Worker             ImFormatString(p, buf_end - p, "TabBar (%d tabs)%s", tab_bar->Tabs.Size, (tab_bar->PrevFrameVisible < ImGui::GetFrameCount() - 2) ? " *Inactive*" : "");
9430*61046927SAndroid Build Coastguard Worker             if (ImGui::TreeNode(tab_bar, "%s", buf))
9431*61046927SAndroid Build Coastguard Worker             {
9432*61046927SAndroid Build Coastguard Worker                 for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
9433*61046927SAndroid Build Coastguard Worker                 {
9434*61046927SAndroid Build Coastguard Worker                     const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
9435*61046927SAndroid Build Coastguard Worker                     ImGui::PushID(tab);
9436*61046927SAndroid Build Coastguard Worker                     if (ImGui::SmallButton("<")) { TabBarQueueChangeTabOrder(tab_bar, tab, -1); } ImGui::SameLine(0, 2);
9437*61046927SAndroid Build Coastguard Worker                     if (ImGui::SmallButton(">")) { TabBarQueueChangeTabOrder(tab_bar, tab, +1); } ImGui::SameLine();
9438*61046927SAndroid Build Coastguard Worker                     ImGui::Text("%02d%c Tab 0x%08X", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID);
9439*61046927SAndroid Build Coastguard Worker                     ImGui::PopID();
9440*61046927SAndroid Build Coastguard Worker                 }
9441*61046927SAndroid Build Coastguard Worker                 ImGui::TreePop();
9442*61046927SAndroid Build Coastguard Worker             }
9443*61046927SAndroid Build Coastguard Worker         }
9444*61046927SAndroid Build Coastguard Worker     };
9445*61046927SAndroid Build Coastguard Worker 
9446*61046927SAndroid Build Coastguard Worker     // Access private state, we are going to display the draw lists from last frame
9447*61046927SAndroid Build Coastguard Worker     ImGuiContext& g = *GImGui;
9448*61046927SAndroid Build Coastguard Worker     Funcs::NodeWindows(g.Windows, "Windows");
9449*61046927SAndroid Build Coastguard Worker     if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size))
9450*61046927SAndroid Build Coastguard Worker     {
9451*61046927SAndroid Build Coastguard Worker         for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++)
9452*61046927SAndroid Build Coastguard Worker             Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList");
9453*61046927SAndroid Build Coastguard Worker         ImGui::TreePop();
9454*61046927SAndroid Build Coastguard Worker     }
9455*61046927SAndroid Build Coastguard Worker     if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
9456*61046927SAndroid Build Coastguard Worker     {
9457*61046927SAndroid Build Coastguard Worker         for (int i = 0; i < g.OpenPopupStack.Size; i++)
9458*61046927SAndroid Build Coastguard Worker         {
9459*61046927SAndroid Build Coastguard Worker             ImGuiWindow* window = g.OpenPopupStack[i].Window;
9460*61046927SAndroid Build Coastguard Worker             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" : "");
9461*61046927SAndroid Build Coastguard Worker         }
9462*61046927SAndroid Build Coastguard Worker         ImGui::TreePop();
9463*61046927SAndroid Build Coastguard Worker     }
9464*61046927SAndroid Build Coastguard Worker     if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size))
9465*61046927SAndroid Build Coastguard Worker     {
9466*61046927SAndroid Build Coastguard Worker         for (int n = 0; n < g.TabBars.Data.Size; n++)
9467*61046927SAndroid Build Coastguard Worker             Funcs::NodeTabBar(g.TabBars.GetByIndex(n));
9468*61046927SAndroid Build Coastguard Worker         ImGui::TreePop();
9469*61046927SAndroid Build Coastguard Worker     }
9470*61046927SAndroid Build Coastguard Worker     if (ImGui::TreeNode("Internal state"))
9471*61046927SAndroid Build Coastguard Worker     {
9472*61046927SAndroid Build Coastguard Worker         const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
9473*61046927SAndroid Build Coastguard Worker         ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
9474*61046927SAndroid Build Coastguard Worker         ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
9475*61046927SAndroid Build Coastguard Worker         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
9476*61046927SAndroid Build Coastguard Worker         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]);
9477*61046927SAndroid Build Coastguard Worker         ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
9478*61046927SAndroid Build Coastguard Worker         ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
9479*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
9480*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
9481*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
9482*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
9483*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
9484*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
9485*61046927SAndroid Build Coastguard Worker         ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
9486*61046927SAndroid Build Coastguard Worker         ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
9487*61046927SAndroid Build Coastguard Worker         ImGui::TreePop();
9488*61046927SAndroid Build Coastguard Worker     }
9489*61046927SAndroid Build Coastguard Worker 
9490*61046927SAndroid Build Coastguard Worker 
9491*61046927SAndroid Build Coastguard Worker     if (g.IO.KeyCtrl && show_window_begin_order)
9492*61046927SAndroid Build Coastguard Worker     {
9493*61046927SAndroid Build Coastguard Worker         for (int n = 0; n < g.Windows.Size; n++)
9494*61046927SAndroid Build Coastguard Worker         {
9495*61046927SAndroid Build Coastguard Worker             ImGuiWindow* window = g.Windows[n];
9496*61046927SAndroid Build Coastguard Worker             if ((window->Flags & ImGuiWindowFlags_ChildWindow) || !window->WasActive)
9497*61046927SAndroid Build Coastguard Worker                 continue;
9498*61046927SAndroid Build Coastguard Worker             char buf[32];
9499*61046927SAndroid Build Coastguard Worker             ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
9500*61046927SAndroid Build Coastguard Worker             float font_size = ImGui::GetFontSize() * 2;
9501*61046927SAndroid Build Coastguard Worker             ImDrawList* overlay_draw_list = GetOverlayDrawList(window);
9502*61046927SAndroid Build Coastguard Worker             overlay_draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
9503*61046927SAndroid Build Coastguard Worker             overlay_draw_list->AddText(NULL, font_size, window->Pos, IM_COL32(255, 255, 255, 255), buf);
9504*61046927SAndroid Build Coastguard Worker         }
9505*61046927SAndroid Build Coastguard Worker     }
9506*61046927SAndroid Build Coastguard Worker     ImGui::End();
9507*61046927SAndroid Build Coastguard Worker }
9508*61046927SAndroid Build Coastguard Worker 
9509*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9510*61046927SAndroid Build Coastguard Worker 
9511*61046927SAndroid Build Coastguard Worker // Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed.
9512*61046927SAndroid Build Coastguard Worker // 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.
9513*61046927SAndroid Build Coastguard Worker #ifdef IMGUI_INCLUDE_IMGUI_USER_INL
9514*61046927SAndroid Build Coastguard Worker #include "imgui_user.inl"
9515*61046927SAndroid Build Coastguard Worker #endif
9516*61046927SAndroid Build Coastguard Worker 
9517*61046927SAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
9518