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