Changeset e66fd66 in opengl-game for IMGUI/imgui.cpp


Ignore:
Timestamp:
Dec 5, 2020, 7:14:31 PM (4 years ago)
Author:
Dmitry Portnoy <dportnoy@…>
Branches:
feature/imgui-sdl, master
Children:
95c657f
Parents:
78c3045
Message:

In OpenGLReference, change all enums to enum classes and update IMGUI to the latest version

File:
1 edited

Legend:

Unmodified
Added
Removed
  • IMGUI/imgui.cpp

    r78c3045 re66fd66  
    1 // dear imgui, v1.61 WIP
     1// dear imgui, v1.79
    22// (main code and documentation)
    33
    4 // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
    5 // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
    6 // Get latest version at https://github.com/ocornut/imgui
    7 // Releases change-log at https://github.com/ocornut/imgui/releases
    8 // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
     4// Help:
     5// - Read FAQ at http://dearimgui.org/faq
     6// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
     7// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
     8// Read imgui.cpp for details, links and comments.
     9
     10// Resources:
     11// - FAQ                   http://dearimgui.org/faq
     12// - Homepage & latest     https://github.com/ocornut/imgui
     13// - Releases & changelog  https://github.com/ocornut/imgui/releases
     14// - Gallery               https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!)
     15// - Glossary              https://github.com/ocornut/imgui/wiki/Glossary
     16// - Wiki                  https://github.com/ocornut/imgui/wiki
     17// - Issues & support      https://github.com/ocornut/imgui/issues
     18
    919// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
    10 // This library is free but I need your support to sustain development and maintenance.
    11 // If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui
     20// See LICENSE.txt for copyright and licensing details (standard MIT License).
     21// This library is free but needs your support to sustain development and maintenance.
     22// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.org".
     23// Individuals: you can support continued development via donations. See docs/README or web page.
    1224
    1325// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
    14 // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without 
    15 // modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't 
    16 // come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you 
     26// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
     27// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
     28// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
    1729// to a better solution or official support for them.
    1830
    1931/*
    2032
    21 Index
     33Index of this file:
     34
     35DOCUMENTATION
     36
    2237- MISSION STATEMENT
    2338- END-USER GUIDE
    24 - PROGRAMMER GUIDE (read me!)
    25 - Read first
    26 - How to update to a newer version of Dear ImGui
    27 - Getting started with integrating Dear ImGui in your code/engine
    28 - Using gamepad/keyboard navigation controls [BETA]
     39- PROGRAMMER GUIDE
     40  - READ FIRST
     41  - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
     42  - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
     43  - HOW A SIMPLE APPLICATION MAY LOOK LIKE
     44  - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
     45  - USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
    2946- API BREAKING CHANGES (read me when you update!)
    30 - ISSUES & TODO LIST
    31 - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
    32 - How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
    33 - How can I display an image? What is ImTextureID, how does it works?
    34 - How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack.
    35 - How can I load a different font than the default?
    36 - How can I easily use icons in my application?
    37 - How can I load multiple fonts?
    38 - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
    39 - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
    40 - I integrated Dear ImGui in my engine and the text or lines are blurry..
    41 - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
    42 - How can I help?
    43 - ISSUES & TODO-LIST
    44 - CODE
    45 
    46 
    47 MISSION STATEMENT
    48 =================
    49 
    50 - Easy to use to create code-driven and data-driven tools
    51 - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools
    52 - Easy to hack and improve
    53 - Minimize screen real-estate usage
    54 - Minimize setup and maintenance
    55 - Minimize state storage on user side
    56 - Portable, minimize dependencies, run on target (consoles, phones, etc.)
    57 - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,
    58 opening a tree node for the first time, etc. but a typical frame should not allocate anything)
    59 
    60 Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
    61 - Doesn't look fancy, doesn't animate
    62 - Limited layout features, intricate layouts are typically crafted in code
    63 
    64 
    65 END-USER GUIDE
    66 ==============
    67 
    68 - Double-click on title bar to collapse window.
    69 - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
    70 - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
    71 - Click and drag on any empty space to move window.
    72 - TAB/SHIFT+TAB to cycle through keyboard editable fields.
    73 - CTRL+Click on a slider or drag box to input value as text.
    74 - Use mouse wheel to scroll.
    75 - Text editor:
    76 - Hold SHIFT or use mouse to select text.
    77 - CTRL+Left/Right to word jump.
    78 - CTRL+Shift+Left/Right to select words.
    79 - CTRL+A our Double-Click to select all.
    80 - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
    81 - CTRL+Z,CTRL+Y to undo/redo.
    82 - ESCAPE to revert text to its original value.
    83 - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
    84 - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
    85 - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
    86 - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW
    87 
    88 
    89 PROGRAMMER GUIDE
    90 ================
    91 
    92 READ FIRST
    93 
    94 - Read the FAQ below this section!
    95 - 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
    96 or destruction steps, less data retention on your side, less state duplication, less state synchronization, less bugs.
    97 - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
    98 - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861
    99 
    100 HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
    101 
    102 - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
    103 - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
    104 If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
    105 from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
    106 likely be a comment about it. Please report any issue to the GitHub page!
    107 - Try to keep your copy of dear imgui reasonably up to date.
    108 
    109 GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
    110 
    111 - Run and study the examples and demo to get acquainted with the library.
    112 - Add the Dear ImGui source files to your projects, using your preferred build system.
    113 It is recommended you build the .cpp files as part of your project and not as a library.
    114 - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
    115 - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder.
    116 - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
    117 
    118 - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize
    119 (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic
    120 integration you don't need to worry about it all.
    121 - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.
    122 - Every frame:
    123 - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)
    124 - Call ImGui::NewFrame() to begin the frame
    125 - You can use any ImGui function you want between NewFrame() and Render()
    126 - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.
    127 (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwise some features will break)
    128 - All rendering information are stored into command-lists until ImGui::Render() is called.
    129 - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.
    130 - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases
    131 of your own application.
    132 - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.
    133 - A minimal application skeleton may be:
    134 
    135 // Application init
    136 ImGui::CreateContext();
    137 ImGuiIO& io = ImGui::GetIO();
    138 io.DisplaySize.x = 1920.0f;
    139 io.DisplaySize.y = 1280.0f;
    140 // TODO: Fill others settings of the io structure later.
    141 
    142 // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)
    143 unsigned char* pixels;
    144 int width, height;
    145 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
    146 // TODO: At this points you've got the texture data and you need to upload that your your graphic system:
    147 MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA)
    148 // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer.
    149 io.Fonts->TexID = (void*)texture;
    150 
    151 // Application main loop
    152 while (true)
    153 {
    154 // Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
    155 ImGuiIO& io = ImGui::GetIO();
    156 io.DeltaTime = 1.0f/60.0f;
    157 io.MousePos = mouse_pos;
    158 io.MouseDown[0] = mouse_button_0;
    159 io.MouseDown[1] = mouse_button_1;
    160 
    161 // Call NewFrame(), after this point you can use ImGui::* functions anytime
    162 ImGui::NewFrame();
    163 
    164 // Most of your application code here
    165 MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
    166 MyGameRender(); // may use any ImGui functions as well!
    167 
    168 // Render & swap video buffers
    169 ImGui::Render();
    170 MyImGuiRenderFunction(ImGui::GetDrawData());
    171 SwapBuffers();
    172 }
    173 
    174 // Shutdown
    175 ImGui::DestroyContext();
    176 
    177 
    178 - A minimal render function skeleton may be:
    179 
    180 void void MyRenderFunction(ImDrawData* draw_data)
    181 {
    182 // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
    183 // TODO: Setup viewport, orthographic projection matrix
    184 // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
    185 for (int n = 0; n < draw_data->CmdListsCount; n++)
    186 {
    187 const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;  // vertex buffer generated by ImGui
    188 const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;   // index buffer generated by ImGui
    189 for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
    190 {
    191 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
    192 if (pcmd->UserCallback)
    193 {
    194 pcmd->UserCallback(cmd_list, pcmd);
    195 }
    196 else
    197 {
    198 // The texture for the draw call is specified by pcmd->TextureId.
    199 // The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization.
    200 MyEngineBindTexture(pcmd->TextureId);
    201 
    202 // We are using scissoring to clip some objects. All low-level graphics API supports it.
    203 // If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
    204 // (some elements visible outside their bounds) but you can fix that once everywhere else works!
    205 MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
    206 
    207 // Render 'pcmd->ElemCount/3' indexed triangles.
    208 // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices.
    209 MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
    210 }
    211 idx_buffer += pcmd->ElemCount;
    212 }
    213 }
    214 }
    215 
    216 - The examples/ folders contains many functional implementation of the pseudo-code above.
    217 - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated.
    218 They tell you if ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the rest of your application.
    219 However, in both cases you need to pass on the inputs to imgui. Read the FAQ below for more information about those flags.
    220 - Please read the FAQ above. Amusingly, it is called a FAQ because people frequently have the same issues!
    221 
    222 USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA]
    223 
    224 - The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787
    225 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
    226 - Gamepad:
    227 - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
    228 - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
    229 Note that io.NavInputs[] is cleared by EndFrame().
    230 - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
    231 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
    232 - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
    233 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.).
    234 - You can download PNG/PSD files depicting the gamepad controls for common controllers at: goo.gl/9LgVZW.
    235 - 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
    236 to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
    237 - Keyboard:
    238 - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
    239 NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
    240 - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
    241 will be set. For more advanced uses, you may want to read from:
    242 - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
    243 - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
    244 - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
    245 Please reach out if you think the game vs navigation input sharing could be improved.
    246 - Mouse:
    247 - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
    248 - 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.
    249 - 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.
    250 Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
    251 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.
    252 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.
    253 (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!)
    254 (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
    255 to set a boolean to ignore your other external mouse positions until the external source is moved again.)
    256 
    257 
    258 API BREAKING CHANGES
    259 ====================
    260 
    261 Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
    262 Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
    263 Also read releases logs https://github.com/ocornut/imgui/releases for more details.
    264 
    265 - 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", consistent with other functions. Kept redirection functions (will obsolete).
    266 - 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.
    267 - 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).
    268 - 2018/03/12 (1.60) - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
    269 - 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.
    270 - 2018/03/03 (1.60) - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
    271 - 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.
    272 - 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.
    273 - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
    274 - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
    275 - removed Shutdown() function, as DestroyContext() serve this purpose.
    276 - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
    277 - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
    278 - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
    279 - 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.
    280 - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
    281 - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
    282 - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
    283 - 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.
    284 - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
    285 - 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
    286 - 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.
    287 - 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.
    288 - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
    289 - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
    290 - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
    291 - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
    292 - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
    293 - 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.
    294 - 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.
    295 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.
    296 - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
    297 - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
    298 - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
    299 - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
    300 - 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.
    301 - 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.
    302 - 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.
    303 removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
    304 - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
    305 - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
    306 - 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).
    307 - 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)".
    308 - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
    309 - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
    310 - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
    311 - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
    312 - 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.
    313 - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
    314 - 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.
    315 - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
    316 - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
    317 - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
    318 - 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.
    319 - 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.
    320 - 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))'
    321 - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
    322 - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
    323 - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
    324 - 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().
    325 - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
    326 - 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.
    327 - 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.
    328 - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
    329 If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you.
    330 However 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.
    331 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.
    332 ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
    333 {
    334 float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
    335 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);
    336 }
    337 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.
    338 - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
    339 - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
    340 - 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).
    341 - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::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.
    342 - 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).
    343 - 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)
    344 - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
    345 - 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.
    346 - 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.
    347 - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
    348 - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
    349 - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
    350 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.
    351 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!
    352 - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
    353 - 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.
    354 - 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
    355 - 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.
    356 you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
    357 - 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.
    358 this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
    359 - 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.
    360 - the signature of the io.RenderDrawListsFn handler has changed!
    361 old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
    362 new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
    363 argument:   'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
    364 ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
    365 ImDrawCmd:  'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
    366 - 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.
    367 - 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!
    368 - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
    369 - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
    370 - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
    371 - 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.
    372 - 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
    373 - 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!
    374 - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
    375 - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
    376 - 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.
    377 - 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.
    378 - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
    379 - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
    380 - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
    381 - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
    382 - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
    383 - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
    384 - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
    385 - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
    386 - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
    387 - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
    388 - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
    389 - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
    390 - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
    391 - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
    392 - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
    393 - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
    394 - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
    395 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
    396 font init:  const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>
    397 became:     unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier;
    398 you now more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
    399 it is now recommended that you sample the font texture with bilinear interpolation.
    400 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
    401 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
    402 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
    403 - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
    404 - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
    405 - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
    406 - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
    407 - 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)
    408 - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
    409 - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
    410 - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
    411 - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
    412 - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
    413 - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
    414 
    415 
    416 ISSUES & TODO-LIST
    417 ==================
    418 See TODO.txt
    419 
    420 
    421 FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
    422 ======================================
    423 
    424 Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
    425 A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure.
    426 - 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.
    427 - 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.
    428 - 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).
    429 Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false.
    430 This is because imgui needs to detect that you clicked in the void to unfocus its windows.
    431 Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!).
    432 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.
    433 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
    434 perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to NewFrameUpdateHoveredWindowAndCaptureFlags().
    435 Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically
    436 have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
    437 were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
    438 
    439 Q: How can I display an image? What is ImTextureID, how does it works?
    440 A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function.
    441 Dear ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry!
    442 It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.
    443 At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.
    444 Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.
    445 (C++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)
    446 To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.
    447 Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.
    448 You may call ImGui::ShowMetricsWindow() to explore active draw lists and visualize/understand how the draw data is generated.
    449 It is your responsibility to get textures uploaded to your GPU.
    450 
    451 Q: How can I have multiple widgets with the same label or without a label?
    452 A: A primer on labels and the ID Stack...
    453 
    454 - Elements that are typically not clickable, such as Text() items don't need an ID.
    455 
    456 - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui
    457 often needs to remember what is the "active" widget). To do so they need a unique ID. Unique ID
    458 are typically derived from a string label, an integer index or a pointer.
    459 
    460 Button("OK");          // Label = "OK",     ID = top of id stack + hash of "OK"
    461 Button("Cancel");      // Label = "Cancel", ID = top of id stack + hash of "Cancel"
    462 
    463 - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
    464 two buttons labeled "OK" in different windows or different tree locations is fine.
    465 
    466 - If you have a same ID twice in the same location, you'll have a conflict:
    467 
    468 Button("OK");
    469 Button("OK");          // ID collision! Interacting with either button will trigger the first one.
    470 
    471 Fear not! this is easy to solve and there are many ways to solve it!
    472 
    473 - Solving ID conflict in a simple/local context:
    474 When passing a label you can optionally specify extra ID information within string itself.
    475 Use "##" to pass a complement to the ID that won't be visible to the end-user.
    476 This helps solving the simple collision cases when you know e.g. at compilation time which items
    477 are going to be created:
    478 
    479 Button("Play");        // Label = "Play",   ID = top of id stack + hash of "Play"
    480 Button("Play##foo1");  // Label = "Play",   ID = top of id stack + hash of "Play##foo1" (different from above)
    481 Button("Play##foo2");  // Label = "Play",   ID = top of id stack + hash of "Play##foo2" (different from above)
    482 
    483 - If you want to completely hide the label, but still need an ID:
    484 
    485 Checkbox("##On", &b);  // Label = "",       ID = top of id stack + hash of "##On" (no label!)
    486 
    487 - Occasionally/rarely you might want change a label while preserving a constant ID. This allows
    488 you to animate labels. For example you may want to include varying information in a window title bar,
    489 but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
    490 
    491 Button("Hello###ID";   // Label = "Hello",  ID = top of id stack + hash of "ID"
    492 Button("World###ID";   // Label = "World",  ID = top of id stack + hash of "ID" (same as above)
    493 
    494 sprintf(buf, "My game (%f FPS)###MyGame", fps);
    495 Begin(buf);            // Variable label,   ID = hash of "MyGame"
    496 
    497 - Solving ID conflict in a more general manner:
    498 Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
    499 within the same window. This is the most convenient way of distinguishing ID when iterating and
    500 creating many UI elements programmatically.
    501 You can push a pointer, a string or an integer value into the ID stack.
    502 Remember that ID are formed from the concatenation of _everything_ in the ID stack!
    503 
    504 for (int i = 0; i < 100; i++)
    505 {
    506 PushID(i);
    507 Button("Click");   // Label = "Click",  ID = top of id stack + hash of integer + hash of "Click"
    508 PopID();
    509 }
    510 
    511 for (int i = 0; i < 100; i++)
    512 {
    513 MyObject* obj = Objects[i];
    514 PushID(obj);
    515 Button("Click");   // Label = "Click",  ID = top of id stack + hash of pointer + hash of "Click"
    516 PopID();
    517 }
    518 
    519 for (int i = 0; i < 100; i++)
    520 {
    521 MyObject* obj = Objects[i];
    522 PushID(obj->Name);
    523 Button("Click");   // Label = "Click",  ID = top of id stack + hash of string + hash of "Click"
    524 PopID();
    525 }
    526 
    527 - More example showing that you can stack multiple prefixes into the ID stack:
    528 
    529 Button("Click");     // Label = "Click",  ID = top of id stack + hash of "Click"
    530 PushID("node");
    531 Button("Click");     // Label = "Click",  ID = top of id stack + hash of "node" + hash of "Click"
    532 PushID(my_ptr);
    533 Button("Click"); // Label = "Click",  ID = top of id stack + hash of "node" + hash of ptr + hash of "Click"
    534 PopID();
    535 PopID();
    536 
    537 - Tree nodes implicitly creates a scope for you by calling PushID().
    538 
    539 Button("Click");     // Label = "Click",  ID = top of id stack + hash of "Click"
    540 if (TreeNode("node"))
    541 {
    542 Button("Click");   // Label = "Click",  ID = top of id stack + hash of "node" + hash of "Click"
    543 TreePop();
    544 }
    545 
    546 - When working with trees, ID are used to preserve the open/close state of each tree node.
    547 Depending on your use cases you may want to use strings, indices or pointers as ID.
    548 e.g. when following a single pointer that may change over time, using a static string as ID
    549 will preserve your node open/closed state when the targeted object change.
    550 e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
    551 node open/closed state differently. See what makes more sense in your situation!
    552 
    553 Q: How can I load a different font than the default?
    554 A: Use the font atlas to load the TTF/OTF file you want:
    555 ImGuiIO& io = ImGui::GetIO();
    556 io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
    557 io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
    558 (default is ProggyClean.ttf, rendered at size 13, embedded in dear imgui's source code)
    559 
    560 New programmers: remember that in C/C++ and most programming languages if you want to use a
    561 backslash \ within a string literal, you need to write it double backslash "\\":
    562 io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels);   // WRONG (you are escape the M here!)
    563 io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels);  // CORRECT
    564 io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels);   // ALSO CORRECT
    565 
    566 Q: How can I easily use icons in my application?
    567 A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you
    568 main font. Then you can refer to icons within your strings. Read 'How can I load multiple fonts?'
    569 and the file 'misc/fonts/README.txt' for instructions and useful header files.
    570 
    571 Q: How can I load multiple fonts?
    572 A: Use the font atlas to pack them into a single texture:
    573 (Read misc/fonts/README.txt and the code in ImFontAtlas for more details.)
    574 
    575 ImGuiIO& io = ImGui::GetIO();
    576 ImFont* font0 = io.Fonts->AddFontDefault();
    577 ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
    578 ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
    579 io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
    580 // the first loaded font gets used by default
    581 // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
    582 
    583 // Options
    584 ImFontConfig config;
    585 config.OversampleH = 3;
    586 config.OversampleV = 1;
    587 config.GlyphOffset.y -= 2.0f;      // Move everything by 2 pixels up
    588 config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
    589 io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config);
    590 
    591 // Combine multiple fonts into one (e.g. for icon fonts)
    592 ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
    593 ImFontConfig config;
    594 config.MergeMode = true;
    595 io.Fonts->AddFontDefault();
    596 io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
    597 io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
    598 
    599 Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
    600 A: When loading a font, pass custom Unicode ranges to specify the glyphs to load.
    601 
    602 // Add default Japanese ranges
    603 io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
    604 
    605 // 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)
    606 ImVector<ImWchar> ranges;
    607 ImFontAtlas::GlyphRangesBuilder builder;
    608 builder.AddText("Hello world");                        // Add a string (here "Hello world" contains 7 unique characters)
    609 builder.AddChar(0x7262);                               // Add a specific character
    610 builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
    611 builder.BuildRanges(&ranges);                          // Build the final result (ordered ranges with all the unique characters submitted)
    612 io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
    613 
    614 All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
    615 by using the u8"hello" syntax. Specifying literal in your source code using a local code page
    616 (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
    617 Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
    618 
    619 Text input: it is up to your application to pass the right character code by calling
    620 io.AddInputCharacter(). The applications in examples/ are doing that. For languages relying
    621 on an Input Method Editor (IME), on Windows you can copy the Hwnd of your application in the
    622 io.ImeWindowHandle field. The default implementation of io.ImeSetInputScreenPosFn() will set
    623 your Microsoft IME position correctly.
    624 
    625 Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
    626 A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags.
    627 Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
    628 - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows.
    629 - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData.
    630 
    631 Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
    632 A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
    633 Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
    634 
    635 Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
    636 A: You are probably mishandling the clipping rectangles in your render function.
    637 Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
    638 
    639 Q: How can I help?
    640 A: - If you are experienced with Dear ImGui and C++, look at the github issues, or TODO.txt and see how you want/can help!
    641 - Convince your company to fund development time! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README.
    642 - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
    643 You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers.
    644 But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
    645 - 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).
    646 
    647 - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
    648 this is also useful to set yourself in the context of another window (to get/set other settings)
    649 - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
    650 - 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
    651 of a deep nested inner loop in your code.
    652 - tip: you can call Render() multiple times (e.g for VR renders).
    653 - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui!
     47- FREQUENTLY ASKED QUESTIONS (FAQ)
     48  - Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
     49
     50CODE
     51(search for "[SECTION]" in the code to find them)
     52
     53// [SECTION] INCLUDES
     54// [SECTION] FORWARD DECLARATIONS
     55// [SECTION] CONTEXT AND MEMORY ALLOCATORS
     56// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
     57// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
     58// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions)
     59// [SECTION] MISC HELPERS/UTILITIES (File functions)
     60// [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
     61// [SECTION] MISC HELPERS/UTILITIES (Color functions)
     62// [SECTION] ImGuiStorage
     63// [SECTION] ImGuiTextFilter
     64// [SECTION] ImGuiTextBuffer
     65// [SECTION] ImGuiListClipper
     66// [SECTION] STYLING
     67// [SECTION] RENDER HELPERS
     68// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
     69// [SECTION] ERROR CHECKING
     70// [SECTION] LAYOUT
     71// [SECTION] SCROLLING
     72// [SECTION] TOOLTIPS
     73// [SECTION] POPUPS
     74// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
     75// [SECTION] DRAG AND DROP
     76// [SECTION] LOGGING/CAPTURING
     77// [SECTION] SETTINGS
     78// [SECTION] PLATFORM DEPENDENT HELPERS
     79// [SECTION] METRICS/DEBUG WINDOW
    65480
    65581*/
     82
     83//-----------------------------------------------------------------------------
     84// DOCUMENTATION
     85//-----------------------------------------------------------------------------
     86
     87/*
     88
     89 MISSION STATEMENT
     90 =================
     91
     92 - Easy to use to create code-driven and data-driven tools.
     93 - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
     94 - Easy to hack and improve.
     95 - Minimize setup and maintenance.
     96 - Minimize state storage on user side.
     97 - Portable, minimize dependencies, run on target (consoles, phones, etc.).
     98 - Efficient runtime and memory consumption.
     99
     100 Designed for developers and content-creators, not the typical end-user! Some of the current weaknesses includes:
     101
     102 - Doesn't look fancy, doesn't animate.
     103 - Limited layout features, intricate layouts are typically crafted in code.
     104
     105
     106 END-USER GUIDE
     107 ==============
     108
     109 - Double-click on title bar to collapse window.
     110 - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
     111 - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
     112 - Click and drag on any empty space to move window.
     113 - TAB/SHIFT+TAB to cycle through keyboard editable fields.
     114 - CTRL+Click on a slider or drag box to input value as text.
     115 - Use mouse wheel to scroll.
     116 - Text editor:
     117   - Hold SHIFT or use mouse to select text.
     118   - CTRL+Left/Right to word jump.
     119   - CTRL+Shift+Left/Right to select words.
     120   - CTRL+A our Double-Click to select all.
     121   - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
     122   - CTRL+Z,CTRL+Y to undo/redo.
     123   - ESCAPE to revert text to its original value.
     124   - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
     125   - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
     126 - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
     127 - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW
     128
     129
     130 PROGRAMMER GUIDE
     131 ================
     132
     133 READ FIRST
     134 ----------
     135 - Remember to read the FAQ (https://www.dearimgui.org/faq)
     136 - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction
     137   or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs.
     138 - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
     139 - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
     140 - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
     141   You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in the FAQ.
     142 - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances.
     143   For every application frame your UI code will be called only once. This is in contrast to e.g. Unity's own implementation of an IMGUI,
     144   where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches.
     145 - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right.
     146 - This codebase is also optimized to yield decent performances with typical "Debug" builds settings.
     147 - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected).
     148   If you get an assert, read the messages and comments around the assert.
     149 - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace.
     150 - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
     151   See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
     152   However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase.
     153 - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!).
     154
     155
     156 HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
     157 ----------------------------------------------
     158 - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
     159 - Or maintain your own branch where you have imconfig.h modified.
     160 - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
     161   If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
     162   from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
     163   likely be a comment about it. Please report any issue to the GitHub page!
     164 - Try to keep your copy of dear imgui reasonably up to date.
     165
     166
     167 GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
     168 ---------------------------------------------------------------
     169 - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
     170 - In the majority of cases you should be able to use unmodified back-ends files available in the examples/ folder.
     171 - Add the Dear ImGui source files + selected back-end source files to your projects or using your preferred build system.
     172   It is recommended you build and statically link the .cpp files as part of your project and NOT as shared library (DLL).
     173 - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types.
     174 - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
     175 - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide.
     176   Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
     177   phases of your own application. All rendering information are stored into command-lists that you will retrieve after calling ImGui::Render().
     178 - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
     179 - 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.
     180
     181
     182 HOW A SIMPLE APPLICATION MAY LOOK LIKE
     183 --------------------------------------
     184 EXHIBIT 1: USING THE EXAMPLE BINDINGS (= imgui_impl_XXX.cpp files from the examples/ folder).
     185 The sub-folders in examples/ contains examples applications following this structure.
     186
     187     // Application init: create a dear imgui context, setup some options, load fonts
     188     ImGui::CreateContext();
     189     ImGuiIO& io = ImGui::GetIO();
     190     // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
     191     // TODO: Fill optional fields of the io structure later.
     192     // TODO: Load TTF/OTF fonts if you don't want to use the default font.
     193
     194     // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32.cpp and imgui_impl_dx11.cpp)
     195     ImGui_ImplWin32_Init(hwnd);
     196     ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
     197
     198     // Application main loop
     199     while (true)
     200     {
     201         // Feed inputs to dear imgui, start new frame
     202         ImGui_ImplDX11_NewFrame();
     203         ImGui_ImplWin32_NewFrame();
     204         ImGui::NewFrame();
     205
     206         // Any application code here
     207         ImGui::Text("Hello, world!");
     208
     209         // Render dear imgui into screen
     210         ImGui::Render();
     211         ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
     212         g_pSwapChain->Present(1, 0);
     213     }
     214
     215     // Shutdown
     216     ImGui_ImplDX11_Shutdown();
     217     ImGui_ImplWin32_Shutdown();
     218     ImGui::DestroyContext();
     219
     220 EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE
     221
     222     // Application init: create a dear imgui context, setup some options, load fonts
     223     ImGui::CreateContext();
     224     ImGuiIO& io = ImGui::GetIO();
     225     // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
     226     // TODO: Fill optional fields of the io structure later.
     227     // TODO: Load TTF/OTF fonts if you don't want to use the default font.
     228
     229     // Build and load the texture atlas into a texture
     230     // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
     231     int width, height;
     232     unsigned char* pixels = NULL;
     233     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
     234
     235     // At this point you've got the texture data and you need to upload that your your graphic system:
     236     // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
     237     // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID.
     238     MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
     239     io.Fonts->TexID = (void*)texture;
     240
     241     // Application main loop
     242     while (true)
     243     {
     244        // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
     245        // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings)
     246        io.DeltaTime = 1.0f/60.0f;              // set the time elapsed since the previous frame (in seconds)
     247        io.DisplaySize.x = 1920.0f;             // set the current display width
     248        io.DisplaySize.y = 1280.0f;             // set the current display height here
     249        io.MousePos = my_mouse_pos;             // set the mouse position
     250        io.MouseDown[0] = my_mouse_buttons[0];  // set the mouse button states
     251        io.MouseDown[1] = my_mouse_buttons[1];
     252
     253        // Call NewFrame(), after this point you can use ImGui::* functions anytime
     254        // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use Dear ImGui everywhere)
     255        ImGui::NewFrame();
     256
     257        // Most of your application code here
     258        ImGui::Text("Hello, world!");
     259        MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
     260        MyGameRender(); // may use any Dear ImGui functions as well!
     261
     262        // Render dear imgui, swap buffers
     263        // (You want to try calling EndFrame/Render as late as you can, to be able to use Dear ImGui in your own game rendering code)
     264        ImGui::EndFrame();
     265        ImGui::Render();
     266        ImDrawData* draw_data = ImGui::GetDrawData();
     267        MyImGuiRenderFunction(draw_data);
     268        SwapBuffers();
     269     }
     270
     271     // Shutdown
     272     ImGui::DestroyContext();
     273
     274 To decide whether to dispatch mouse/keyboard inputs to Dear ImGui to the rest your application,
     275 you should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags!
     276 Please read the FAQ and example applications for details about this!
     277
     278
     279 HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
     280 ---------------------------------------------
     281 The bindings in impl_impl_XXX.cpp files contains many working implementations of a rendering function.
     282
     283    void void MyImGuiRenderFunction(ImDrawData* draw_data)
     284    {
     285       // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
     286       // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
     287       // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
     288       // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
     289       for (int n = 0; n < draw_data->CmdListsCount; n++)
     290       {
     291          const ImDrawList* cmd_list = draw_data->CmdLists[n];
     292          const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;  // vertex buffer generated by Dear ImGui
     293          const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;   // index buffer generated by Dear ImGui
     294          for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
     295          {
     296             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
     297             if (pcmd->UserCallback)
     298             {
     299                 pcmd->UserCallback(cmd_list, pcmd);
     300             }
     301             else
     302             {
     303                 // The texture for the draw call is specified by pcmd->TextureId.
     304                 // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
     305                 MyEngineBindTexture((MyTexture*)pcmd->TextureId);
     306
     307                 // We are using scissoring to clip some objects. All low-level graphics API should supports it.
     308                 // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
     309                 //   (some elements visible outside their bounds) but you can fix that once everything else works!
     310                 // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize)
     311                 //   In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize.
     312                 //   However, in the interest of supporting multi-viewport applications in the future (see 'viewport' branch on github),
     313                 //   always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
     314                 // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
     315                 ImVec2 pos = draw_data->DisplayPos;
     316                 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));
     317
     318                 // Render 'pcmd->ElemCount/3' indexed triangles.
     319                 // By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices.
     320                 MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
     321             }
     322             idx_buffer += pcmd->ElemCount;
     323          }
     324       }
     325    }
     326
     327
     328 USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
     329 ------------------------------------------
     330 - The gamepad/keyboard navigation is fairly functional and keeps being improved.
     331 - Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse!
     332 - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
     333 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
     334 - Keyboard:
     335    - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
     336      NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
     337    - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
     338      will be set. For more advanced uses, you may want to read from:
     339       - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
     340       - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
     341       - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
     342      Please reach out if you think the game vs navigation input sharing could be improved.
     343 - Gamepad:
     344    - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
     345    - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
     346      Note that io.NavInputs[] is cleared by EndFrame().
     347    - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
     348         0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
     349    - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
     350      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.).
     351    - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://goo.gl/9LgVZW.
     352    - 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
     353      to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
     354 - Mouse:
     355    - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
     356    - 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.
     357    - 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.
     358      Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
     359      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.
     360      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.
     361      (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!)
     362      (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
     363       to set a boolean to ignore your other external mouse positions until the external source is moved again.)
     364
     365
     366 API BREAKING CHANGES
     367 ====================
     368
     369 Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
     370 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.
     371 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.
     372 You can read releases logs https://github.com/ocornut/imgui/releases for more details.
     373
     374 - 2020/10/05 (1.79) - removed ImGuiListClipper: Renamed constructor parameters which created an ambiguous alternative to using the ImGuiListClipper::Begin() function, with misleading edge cases (note: imgui_memory_editor <0.40 from imgui_club/ used this old clipper API. Update your copy if needed).
     375 - 2020/09/25 (1.79) - renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete sooner because previous name was added recently).
     376 - 2020/09/25 (1.79) - renamed style.TabMinWidthForUnselectedCloseButton to style.TabMinWidthForCloseButton.
     377 - 2020/09/21 (1.79) - renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), reverting the change from 1.77. For varieties of reason this is more self-explanatory.
     378 - 2020/09/21 (1.79) - removed return value from OpenPopupOnItemClick() - returned true on mouse release on item - because it is inconsistent with other popup APIs and makes others misleading. It's also and unnecessary: you can use IsWindowAppearing() after BeginPopup() for a similar result.
     379 - 2020/09/17 (1.79) - removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied after scaling and not very meaningful/useful outside of being needed by the default ProggyClean font. If you scaled this value after calling AddFontDefault(), this is now done automatically. It was also getting in the way of better font scaling, so let's get rid of it now!
     380 - 2020/08/17 (1.78) - obsoleted use of the trailing 'float power=1.0f' parameter for DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN(), VSliderFloat() and VSliderScalar().
     381                       replaced the 'float power=1.0f' argument with integer-based flags defaulting to 0 (as with all our flags).
     382                       worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected. in short, when calling those functions:
     383                       - if you omitted the 'power' parameter (likely!), you are not affected.
     384                       - if you set the 'power' parameter to 1.0f (same as previous default value): 1/ your compiler may warn on float>int conversion, 2/ everything else will work. 3/ you can replace the 1.0f value with 0 to fix the warning, and be technically correct.
     385                       - if you set the 'power' parameter to >1.0f (to enable non-linear editing): 1/ your compiler may warn on float>int conversion, 2/ code will assert at runtime, 3/ in case asserts are disabled, the code will not crash and enable the _Logarithmic flag. 4/ you can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert and get a _similar_ effect as previous uses of power >1.0f.
     386                       see https://github.com/ocornut/imgui/issues/3361 for all details.
     387                       kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar(). For those three the 'float power=1.0f' version were removed directly as they were most unlikely ever used.
     388                       for shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
     389                     - obsoleted use of v_min > v_max in DragInt, DragFloat, DragScalar to lock edits (introduced in 1.73, was not demoed nor documented very), will be replaced by a more generic ReadOnly feature. You may use the ImGuiSliderFlags_ReadOnly internal flag in the meantime.
     390 - 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems.
     391 - 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete). [NOTE: THIS WAS REVERTED IN 1.79]
     392 - 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017.
     393 - 2020/04/23 (1.77) - removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular().
     394 - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more.
     395 - 2019/12/17 (1.75) - [undid this change in 1.76] made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead.
     396 - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value.
     397 - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017):
     398                       - ShowTestWindow()                    -> use ShowDemoWindow()
     399                       - IsRootWindowFocused()               -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow)
     400                       - IsRootWindowOrAnyChildFocused()     -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
     401                       - SetNextWindowContentWidth(w)        -> use SetNextWindowContentSize(ImVec2(w, 0.0f)
     402                       - GetItemsLineHeightWithSpacing()     -> use GetFrameHeightWithSpacing()
     403                       - ImGuiCol_ChildWindowBg              -> use ImGuiCol_ChildBg
     404                       - ImGuiStyleVar_ChildWindowRounding   -> use ImGuiStyleVar_ChildRounding
     405                       - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap
     406                       - IMGUI_DISABLE_TEST_WINDOWS          -> use IMGUI_DISABLE_DEMO_WINDOWS
     407 - 2019/12/08 (1.75) - obsoleted calling ImDrawList::PrimReserve() with a negative count (which was the vaguely documented and rarely if ever used). Instead we added an explicit PrimUnreserve() API.
     408 - 2019/12/06 (1.75) - removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent with other mouse functions (none of the other functions have it).
     409 - 2019/11/21 (1.74) - ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert.
     410 - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS for consistency.
     411 - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS for consistency.
     412 - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017):
     413                       - Begin() [old 5 args version]        -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed
     414                       - IsRootWindowOrAnyChildHovered()     -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows)
     415                       - AlignFirstTextHeightToWidgets()     -> use AlignTextToFramePadding()
     416                       - SetNextWindowPosCenter()            -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f)
     417                       - ImFont::Glyph                       -> use ImFontGlyph
     418 - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function.
     419                       if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix.
     420                       The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay).
     421                       If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you.
     422 - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete).
     423 - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete).
     424 - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names, or see how they were implemented until 1.71.
     425 - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have
     426                       overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering.
     427                       This optimization is disabled if the parent window has no visual output, because it appears to be the most common situation leading to the creation of overlapping child windows.
     428                       Please reach out if you are affected.
     429 - 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
     430 - 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c).
     431 - 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now.
     432 - 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete).
     433 - 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete).
     434 - 2019/02/26 (1.69) - renamed ImGuiColorEditFlags_RGB/ImGuiColorEditFlags_HSV/ImGuiColorEditFlags_HEX to ImGuiColorEditFlags_DisplayRGB/ImGuiColorEditFlags_DisplayHSV/ImGuiColorEditFlags_DisplayHex. Kept redirection enums (will obsolete).
     435 - 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 an arbitrary small value!
     436 - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already).
     437 - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
     438 - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete).
     439 - 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.
     440 - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags.
     441 - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files.
     442 - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
     443 - 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.
     444                       If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths.
     445 - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
     446 - 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.
     447                       NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED.
     448                       Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions.
     449 - 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).
     450 - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete).
     451 - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly).
     452 - 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.
     453 - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency.
     454 - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
     455 - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
     456 - 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.).
     457                       old bindings will still work as is, however prefer using the separated bindings as they will be updated to support multi-viewports.
     458                       when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call.
     459                       in particular, note that old bindings called ImGui::NewFrame() at the end of their ImGui_ImplXXXX_NewFrame() function.
     460 - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
     461 - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
     462 - 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.
     463                       If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
     464                       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.
     465                       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.
     466 - 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",
     467                       consistent with other functions. Kept redirection functions (will obsolete).
     468 - 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.
     469 - 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).
     470 - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
     471 - 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.
     472 - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
     473 - 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.
     474 - 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.
     475 - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
     476                       - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
     477                       - removed Shutdown() function, as DestroyContext() serve this purpose.
     478                       - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
     479                       - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
     480                       - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
     481 - 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.
     482 - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
     483 - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
     484 - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
     485 - 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.
     486 - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
     487 - 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
     488 - 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.
     489 - 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.
     490 - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
     491 - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
     492                     - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
     493 - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
     494 - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
     495 - 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.
     496 - 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.
     497                       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.
     498 - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
     499 - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
     500 - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
     501 - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
     502 - 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.
     503 - 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.
     504 - 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.
     505                       removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
     506                         IsItemHoveredRect()        --> IsItemHovered(ImGuiHoveredFlags_RectOnly)
     507                         IsMouseHoveringAnyWindow() --> IsWindowHovered(ImGuiHoveredFlags_AnyWindow)
     508                         IsMouseHoveringWindow()    --> IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) [weird, old behavior]
     509 - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
     510 - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
     511 - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete).
     512 - 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).
     513 - 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)".
     514 - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
     515                     - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
     516                     - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
     517 - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
     518 - 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.
     519 - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame type.
     520 - 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.
     521 - 2017/08/13 (1.51) - renamed ImGuiCol_Column to ImGuiCol_Separator, ImGuiCol_ColumnHovered to ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive to ImGuiCol_SeparatorActive. Kept redirection enums (will obsolete).
     522 - 2017/08/11 (1.51) - renamed ImGuiSetCond_Always to ImGuiCond_Always, ImGuiSetCond_Once to ImGuiCond_Once, ImGuiSetCond_FirstUseEver to ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing to ImGuiCond_Appearing. Kept redirection enums (will obsolete).
     523 - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
     524 - 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.
     525                     - 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.
     526                     - 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))'
     527 - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
     528 - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
     529 - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
     530 - 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().
     531 - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
     532 - 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.
     533 - 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.
     534 - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
     535                       If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you, otherwise if <1.0f you need tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
     536                       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:
     537                       ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; 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); }
     538                       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.
     539 - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
     540 - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
     541 - 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).
     542 - 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.
     543 - 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).
     544 - 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)
     545 - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
     546 - 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.
     547 - 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.
     548 - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
     549 - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
     550 - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
     551                       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.
     552                       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!
     553 - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
     554 - 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.
     555 - 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
     556 - 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.
     557                       you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
     558 - 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.
     559                       this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
     560                     - 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.
     561                     - the signature of the io.RenderDrawListsFn handler has changed!
     562                       old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
     563                       new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
     564                         parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
     565                         ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
     566                         ImDrawCmd:  'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
     567                     - 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.
     568                     - 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!
     569                     - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
     570 - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
     571 - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
     572 - 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.
     573 - 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
     574 - 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!
     575 - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
     576 - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
     577 - 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.
     578 - 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.
     579 - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
     580 - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
     581 - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
     582 - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
     583 - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
     584 - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
     585 - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
     586 - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
     587 - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
     588 - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
     589 - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
     590 - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
     591 - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
     592 - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
     593 - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
     594 - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
     595 - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
     596 - 2015/01/11 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
     597                       - old:  const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); [..Upload texture to GPU..];
     598                       - new:  unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); [..Upload texture to GPU..]; io.Fonts->TexId = YourTexIdentifier;
     599                       you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. It is now recommended that you sample the font texture with bilinear interpolation.
     600 - 2015/01/11 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
     601 - 2015/01/11 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
     602 - 2015/01/11 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
     603 - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
     604 - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
     605 - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
     606 - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
     607 - 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)
     608 - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
     609 - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
     610 - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
     611 - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
     612 - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
     613 - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
     614
     615
     616 FREQUENTLY ASKED QUESTIONS (FAQ)
     617 ================================
     618
     619 Read all answers online:
     620   https://www.dearimgui.org/faq or https://github.com/ocornut/imgui/blob/master/docs/FAQ.md (same url)
     621 Read all answers locally (with a text editor or ideally a Markdown viewer):
     622   docs/FAQ.md
     623 Some answers are copied down here to facilitate searching in code.
     624
     625 Q&A: Basics
     626 ===========
     627
     628 Q: Where is the documentation?
     629 A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
     630    - Run the examples/ and explore them.
     631    - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
     632    - The demo covers most features of Dear ImGui, so you can read the code and see its output.
     633    - See documentation and comments at the top of imgui.cpp + effectively imgui.h.
     634    - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the
     635      examples/ folder to explain how to integrate Dear ImGui with your own engine/application.
     636    - The Wiki (https://github.com/ocornut/imgui/wiki) has many resources and links.
     637    - The Glossary (https://github.com/ocornut/imgui/wiki/Glossary) page also may be useful.
     638    - Your programming IDE is your friend, find the type or function declaration to find comments
     639      associated to it.
     640
     641 Q: What is this library called?
     642 Q: Which version should I get?
     643 >> This library is called "Dear ImGui", please don't call it "ImGui" :)
     644 >> See https://www.dearimgui.org/faq for details.
     645
     646 Q&A: Integration
     647 ================
     648
     649 Q: How to get started?
     650 A: Read 'PROGRAMMER GUIDE' above. Read examples/README.txt.
     651
     652 Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
     653 A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags!
     654 >> See https://www.dearimgui.org/faq for fully detailed answer. You really want to read this.
     655
     656 Q. How can I enable keyboard controls?
     657 Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
     658 Q: I integrated Dear ImGui in my engine and little squares are showing instead of text..
     659 Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
     660 Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..
     661 >> See https://www.dearimgui.org/faq
     662
     663 Q&A: Usage
     664 ----------
     665
     666 Q: Why is my widget not reacting when I click on it?
     667 Q: How can I have widgets with an empty label?
     668 Q: How can I have multiple widgets with the same label?
     669 Q: How can I display an image? What is ImTextureID, how does it works?
     670 Q: How can I use my own math types instead of ImVec2/ImVec4?
     671 Q: How can I interact with standard C++ types (such as std::string and std::vector)?
     672 Q: How can I display custom shapes? (using low-level ImDrawList API)
     673 >> See https://www.dearimgui.org/faq
     674
     675 Q&A: Fonts, Text
     676 ================
     677
     678 Q: How should I handle DPI in my application?
     679 Q: How can I load a different font than the default?
     680 Q: How can I easily use icons in my application?
     681 Q: How can I load multiple fonts?
     682 Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
     683 >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md
     684
     685 Q&A: Concerns
     686 =============
     687
     688 Q: Who uses Dear ImGui?
     689 Q: Can you create elaborate/serious tools with Dear ImGui?
     690 Q: Can you reskin the look of Dear ImGui?
     691 Q: Why using C++ (as opposed to C)?
     692 >> See https://www.dearimgui.org/faq
     693
     694 Q&A: Community
     695 ==============
     696
     697 Q: How can I help?
     698 A: - Businesses: please reach out to "contact AT dearimgui.org" if you work in a place using Dear ImGui!
     699      We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts.
     700      This is among the most useful thing you can do for Dear ImGui. With increased funding we can hire more people working on this project.
     701    - Individuals: you can support continued development via PayPal donations. See README.
     702    - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt
     703      and see how you want to help and can help!
     704    - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
     705      You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers.
     706      But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
     707    - 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).
     708
     709*/
     710
     711//-------------------------------------------------------------------------
     712// [SECTION] INCLUDES
     713//-------------------------------------------------------------------------
    656714
    657715#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
     
    660718
    661719#include "imgui.h"
     720#ifndef IMGUI_DISABLE
     721
     722#ifndef IMGUI_DEFINE_MATH_OPERATORS
    662723#define IMGUI_DEFINE_MATH_OPERATORS
     724#endif
    663725#include "imgui_internal.h"
    664726
    665 #include <ctype.h>      // toupper, isprint
    666 #include <stdlib.h>     // NULL, malloc, free, qsort, atoi
     727// System includes
     728#include <ctype.h>      // toupper
    667729#include <stdio.h>      // vsnprintf, sscanf, printf
    668730#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
     
    672734#endif
    673735
    674 #define IMGUI_DEBUG_NAV_SCORING     0
    675 #define IMGUI_DEBUG_NAV_RECTS       0
     736// [Windows] OS specific includes (optional)
     737#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
     738#define IMGUI_DISABLE_WIN32_FUNCTIONS
     739#endif
     740#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
     741#ifndef WIN32_LEAN_AND_MEAN
     742#define WIN32_LEAN_AND_MEAN
     743#endif
     744#ifndef NOMINMAX
     745#define NOMINMAX
     746#endif
     747#ifndef __MINGW32__
     748#include <Windows.h>        // _wfopen, OpenClipboard
     749#else
     750#include <windows.h>
     751#endif
     752#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have all Win32 functions
     753#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
     754#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
     755#endif
     756#endif
     757
     758// [Apple] OS specific includes
     759#if defined(__APPLE__)
     760#include <TargetConditionals.h>
     761#endif
    676762
    677763// Visual Studio warnings
    678764#ifdef _MSC_VER
    679 #pragma warning (disable: 4127) // condition expression is constant
    680 #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
    681 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
     765#pragma warning (disable: 4127)             // condition expression is constant
     766#pragma warning (disable: 4996)             // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
     767#if defined(_MSC_VER) && _MSC_VER >= 1922   // MSVC 2019 16.2 or later
     768#pragma warning (disable: 5054)             // operator '|': deprecated between enumerations of different types
    682769#endif
    683 
    684 // Clang warnings with -Weverything
    685 #ifdef __clang__
    686 #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!
    687 #pragma clang diagnostic ignored "-Wold-style-cast"         // warning : use of old-style cast                              // yes, they are more terse.
    688 #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.
    689 #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.
    690 #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.
    691 #pragma clang diagnostic ignored "-Wglobal-constructors"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.
    692 #pragma clang diagnostic ignored "-Wsign-conversion"        // warning : implicit conversion changes signedness             //
    693 #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.
    694 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
     770#endif
     771
     772// Clang/GCC warnings with -Weverything
     773#if defined(__clang__)
     774#if __has_warning("-Wunknown-warning-option")
     775#pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'                      // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
     776#endif
     777#pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
     778#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast                            // yes, they are more terse.
     779#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.
     780#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.
     781#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.
     782#pragma clang diagnostic ignored "-Wglobal-constructors"            // warning: declaration requires a global destructor         // similar to above, not sure what the exact difference is.
     783#pragma clang diagnostic ignored "-Wsign-conversion"                // warning: implicit conversion changes signedness
     784#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.
     785#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning: cast to 'void *' from smaller integer type 'int'
     786#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant                    // some standard header variations use #define NULL 0
     787#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.
     788#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
    695789#elif defined(__GNUC__)
     790// We disable -Wpragmas because GCC doesn't provide an has_warning equivalent and some forks/patches may not following the warning/version association.
     791#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
    696792#pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
    697793#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
     
    701797#pragma GCC diagnostic ignored "-Wformat-nonliteral"        // warning: format not a string literal, format string not checked
    702798#pragma GCC diagnostic ignored "-Wstrict-overflow"          // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
     799#pragma GCC diagnostic ignored "-Wclass-memaccess"          // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
    703800#endif
    704801
    705 // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
    706 #ifdef _MSC_VER
    707 #define IMGUI_CDECL __cdecl
    708 #else
    709 #define IMGUI_CDECL
    710 #endif
     802// Debug options
     803#define IMGUI_DEBUG_NAV_SCORING     0   // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL
     804#define IMGUI_DEBUG_NAV_RECTS       0   // Display the reference navigation rectangle for each window
     805#define IMGUI_DEBUG_INI_SETTINGS    0   // Save additional comments in .ini file (particularly helps for Docking, but makes saving slower)
     806
     807// 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.
     808static const float NAV_WINDOWING_HIGHLIGHT_DELAY            = 0.20f;    // Time before the highlight and screen dimming starts fading in
     809static const float NAV_WINDOWING_LIST_APPEAR_DELAY          = 0.15f;    // Time before the window list starts to appear
     810
     811// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end)
     812static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f;     // Extend outside and inside windows. Affect FindHoveredWindow().
     813static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;    // Reduce visual noise by only highlighting the border after a certain time.
     814static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER    = 2.00f;    // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
    711815
    712816//-------------------------------------------------------------------------
    713 // Forward Declarations
     817// [SECTION] FORWARD DECLARATIONS
    714818//-------------------------------------------------------------------------
    715819
    716 static bool             IsKeyPressedMap(ImGuiKey key, bool repeat = true);
    717 
    718 static ImFont*          GetDefaultFont();
    719820static void             SetCurrentWindow(ImGuiWindow* window);
    720 static void             SetWindowScrollX(ImGuiWindow* window, float new_scroll_x);
    721 static void             SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
    722 static void             SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
    723 static void             SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
    724 static void             SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
    725 static ImGuiWindow*     FindHoveredWindow();
    726 static ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
    727 static void             CheckStacksSize(ImGuiWindow* window, bool write);
     821static void             FindHoveredWindow();
     822static ImGuiWindow*     CreateNewWindow(const char* name, ImGuiWindowFlags flags);
    728823static ImVec2           CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
    729824
    730825static void             AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
    731 static void             AddWindowToDrawData(ImVector<ImDrawList*>* out_list, ImGuiWindow* window);
    732 static void             AddWindowToSortedBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
    733 
    734 static ImGuiWindowSettings* AddWindowSettings(const char* name);
    735 
    736 static void             LoadIniSettingsFromDisk(const char* ini_filename);
    737 static void             LoadIniSettingsFromMemory(const char* buf);
    738 static void             SaveIniSettingsToDisk(const char* ini_filename);
    739 static void             SaveIniSettingsToMemory(ImVector<char>& out_buf);
    740 static void             MarkIniSettingsDirty(ImGuiWindow* window);
     826static void             AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
    741827
    742828static ImRect           GetViewportRect();
    743829
    744 static void             ClosePopupToLevel(int remaining);
    745 
    746 static bool             InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data);
    747 static int              InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
    748 static ImVec2           InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
    749 
    750 static inline int       DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format);
    751 static void             DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2);
    752 static bool             DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format);
    753 
    754 namespace ImGui
    755 {
    756    static void             NavUpdate();
    757    static void             NavUpdateWindowing();
    758    static void             NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
    759 
    760    static void             UpdateMovingWindow();
    761    static void             UpdateMouseInputs();
    762    static void             UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
    763    static void             FocusFrontMostActiveWindow(ImGuiWindow* ignore_window);
    764 }
    765 
    766 //-----------------------------------------------------------------------------
    767 // Platform dependent default implementations
    768 //-----------------------------------------------------------------------------
    769 
     830// Settings
     831static void             WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
     832static void*            WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
     833static void             WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
     834static void             WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
     835static void             WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
     836
     837// Platform Dependents default implementation for IO functions
    770838static const char*      GetClipboardTextFn_DefaultImpl(void* user_data);
    771839static void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
    772840static void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
    773841
     842namespace ImGui
     843{
     844// Navigation
     845static void             NavUpdate();
     846static void             NavUpdateWindowing();
     847static void             NavUpdateWindowingOverlay();
     848static void             NavUpdateMoveResult();
     849static void             NavUpdateInitResult();
     850static float            NavUpdatePageUpPageDown();
     851static inline void      NavUpdateAnyRequestFlag();
     852static void             NavEndFrame();
     853static bool             NavScoreItem(ImGuiNavMoveResult* result, ImRect cand);
     854static void             NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
     855static ImVec2           NavCalcPreferredRefPos();
     856static void             NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
     857static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
     858static int              FindWindowFocusIndex(ImGuiWindow* window);
     859
     860// Error Checking
     861static void             ErrorCheckNewFrameSanityChecks();
     862static void             ErrorCheckEndFrameSanityChecks();
     863static void             ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write);
     864
     865// Misc
     866static void             UpdateSettings();
     867static void             UpdateMouseInputs();
     868static void             UpdateMouseWheel();
     869static void             UpdateTabFocus();
     870static void             UpdateDebugToolItemPicker();
     871static bool             UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
     872static void             RenderWindowOuterBorders(ImGuiWindow* window);
     873static void             RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
     874static void             RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
     875
     876}
     877
    774878//-----------------------------------------------------------------------------
    775 // Context
     879// [SECTION] CONTEXT AND MEMORY ALLOCATORS
    776880//-----------------------------------------------------------------------------
    777881
    778 // Current context pointer. Implicitly used by all ImGui functions. Always assumed to be != NULL.
    779 // CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
    780 // If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file.
    781 // ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can:
    782 // - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
    783 // - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
     882// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
     883// ImGui::CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
     884// 1) Important: globals are not shared across DLL boundaries! If you use DLLs or any form of hot-reloading: you will need to call
     885//    SetCurrentContext() (with the pointer you got from CreateContext) from each unique static/DLL boundary, and after each hot-reloading.
     886//    In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into.
     887// 2) Important: Dear ImGui functions are not thread-safe because of this pointer.
     888//    If you want thread-safety to allow N threads to access N different contexts, you can:
     889//    - Change this variable to use thread local storage so each thread can refer to a different context, in imconfig.h:
     890//          struct ImGuiContext;
     891//          extern thread_local ImGuiContext* MyImGuiTLS;
     892//          #define GImGui MyImGuiTLS
     893//      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.
     894//    - Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
     895//    - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from different namespace.
    784896#ifndef GImGui
    785897ImGuiContext*   GImGui = NULL;
     
    787899
    788900// Memory Allocator functions. Use SetAllocatorFunctions() to change them.
    789 // If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file. 
     901// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
    790902// 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.
    791903#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
    792 static void*   MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); }
    793 static void    FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); }
     904static void*   MallocWrapper(size_t size, void* user_data)    { IM_UNUSED(user_data); return malloc(size); }
     905static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_data); free(ptr); }
    794906#else
    795 static void*   MallocWrapper(size_t size, void* user_data) { (void)user_data; (void)size; IM_ASSERT(0); return NULL; }
    796 static void    FreeWrapper(void* ptr, void* user_data) { (void)user_data; (void)ptr; IM_ASSERT(0); }
     907static void*   MallocWrapper(size_t size, void* user_data)    { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
     908static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
    797909#endif
    798910
    799911static void*  (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
    800 static void(*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
     912static void   (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
    801913static void*    GImAllocatorUserData = NULL;
    802 static size_t   GImAllocatorActiveAllocationsCount = 0;
    803914
    804915//-----------------------------------------------------------------------------
    805 // User facing structures
     916// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
    806917//-----------------------------------------------------------------------------
    807918
    808919ImGuiStyle::ImGuiStyle()
    809920{
    810    Alpha = 1.0f;             // Global alpha applies to everything in ImGui
    811    WindowPadding = ImVec2(8, 8);      // Padding within a window
    812    WindowRounding = 7.0f;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows
    813    WindowBorderSize = 1.0f;             // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
    814    WindowMinSize = ImVec2(32, 32);    // Minimum window size
    815    WindowTitleAlign = ImVec2(0.0f, 0.5f);// Alignment for title bar text
    816    ChildRounding = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
    817    ChildBorderSize = 1.0f;             // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
    818    PopupRounding = 0.0f;             // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
    819    PopupBorderSize = 1.0f;             // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
    820    FramePadding = ImVec2(4, 3);      // Padding within a framed rectangle (used by most widgets)
    821    FrameRounding = 0.0f;             // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
    822    FrameBorderSize = 0.0f;             // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
    823    ItemSpacing = ImVec2(8, 4);      // Horizontal and vertical spacing between widgets/lines
    824    ItemInnerSpacing = ImVec2(4, 4);      // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
    825    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!
    826    IndentSpacing = 21.0f;            // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
    827    ColumnsMinSpacing = 6.0f;             // Minimum horizontal spacing between two columns
    828    ScrollbarSize = 16.0f;            // Width of the vertical scrollbar, Height of the horizontal scrollbar
    829    ScrollbarRounding = 9.0f;             // Radius of grab corners rounding for scrollbar
    830    GrabMinSize = 10.0f;            // Minimum width/height of a grab box for slider/scrollbar
    831    GrabRounding = 0.0f;             // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
    832    ButtonTextAlign = ImVec2(0.5f, 0.5f);// Alignment of button text when button is larger than text.
    833    DisplayWindowPadding = ImVec2(20, 20);    // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
    834    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.
    835    MouseCursorScale = 1.0f;             // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
    836    AntiAliasedLines = true;             // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
    837    AntiAliasedFill = true;             // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
    838    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.
    839 
    840                                             // Default theme
    841    ImGui::StyleColorsDark(this);
     921    Alpha                   = 1.0f;             // Global alpha applies to everything in ImGui
     922    WindowPadding           = ImVec2(8,8);      // Padding within a window
     923    WindowRounding          = 7.0f;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
     924    WindowBorderSize        = 1.0f;             // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
     925    WindowMinSize           = ImVec2(32,32);    // Minimum window size
     926    WindowTitleAlign        = ImVec2(0.0f,0.5f);// Alignment for title bar text
     927    WindowMenuButtonPosition= ImGuiDir_Left;    // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
     928    ChildRounding           = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
     929    ChildBorderSize         = 1.0f;             // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
     930    PopupRounding           = 0.0f;             // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
     931    PopupBorderSize         = 1.0f;             // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
     932    FramePadding            = ImVec2(4,3);      // Padding within a framed rectangle (used by most widgets)
     933    FrameRounding           = 0.0f;             // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
     934    FrameBorderSize         = 0.0f;             // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
     935    ItemSpacing             = ImVec2(8,4);      // Horizontal and vertical spacing between widgets/lines
     936    ItemInnerSpacing        = ImVec2(4,4);      // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
     937    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!
     938    IndentSpacing           = 21.0f;            // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
     939    ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
     940    ScrollbarSize           = 14.0f;            // Width of the vertical scrollbar, Height of the horizontal scrollbar
     941    ScrollbarRounding       = 9.0f;             // Radius of grab corners rounding for scrollbar
     942    GrabMinSize             = 10.0f;            // Minimum width/height of a grab box for slider/scrollbar
     943    GrabRounding            = 0.0f;             // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
     944    LogSliderDeadzone       = 4.0f;             // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
     945    TabRounding             = 4.0f;             // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
     946    TabBorderSize           = 0.0f;             // Thickness of border around tabs.
     947    TabMinWidthForCloseButton = 0.0f;           // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected.
     948    ColorButtonPosition     = ImGuiDir_Right;   // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
     949    ButtonTextAlign         = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
     950    SelectableTextAlign     = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
     951    DisplayWindowPadding    = ImVec2(19,19);    // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
     952    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.
     953    MouseCursorScale        = 1.0f;             // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
     954    AntiAliasedLines        = true;             // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
     955    AntiAliasedLinesUseTex  = true;             // Enable anti-aliased lines/borders using textures where possible. Require back-end to render with bilinear filtering.
     956    AntiAliasedFill         = true;             // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
     957    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.
     958    CircleSegmentMaxError   = 1.60f;            // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
     959
     960    // Default theme
     961    ImGui::StyleColorsDark(this);
    842962}
    843963
     
    846966void ImGuiStyle::ScaleAllSizes(float scale_factor)
    847967{
    848    WindowPadding = ImFloor(WindowPadding * scale_factor);
    849    WindowRounding = ImFloor(WindowRounding * scale_factor);
    850    WindowMinSize = ImFloor(WindowMinSize * scale_factor);
    851    ChildRounding = ImFloor(ChildRounding * scale_factor);
    852    PopupRounding = ImFloor(PopupRounding * scale_factor);
    853    FramePadding = ImFloor(FramePadding * scale_factor);
    854    FrameRounding = ImFloor(FrameRounding * scale_factor);
    855    ItemSpacing = ImFloor(ItemSpacing * scale_factor);
    856    ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
    857    TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
    858    IndentSpacing = ImFloor(IndentSpacing * scale_factor);
    859    ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
    860    ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
    861    ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
    862    GrabMinSize = ImFloor(GrabMinSize * scale_factor);
    863    GrabRounding = ImFloor(GrabRounding * scale_factor);
    864    DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
    865    DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
    866    MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
     968    WindowPadding = ImFloor(WindowPadding * scale_factor);
     969    WindowRounding = ImFloor(WindowRounding * scale_factor);
     970    WindowMinSize = ImFloor(WindowMinSize * scale_factor);
     971    ChildRounding = ImFloor(ChildRounding * scale_factor);
     972    PopupRounding = ImFloor(PopupRounding * scale_factor);
     973    FramePadding = ImFloor(FramePadding * scale_factor);
     974    FrameRounding = ImFloor(FrameRounding * scale_factor);
     975    ItemSpacing = ImFloor(ItemSpacing * scale_factor);
     976    ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
     977    TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
     978    IndentSpacing = ImFloor(IndentSpacing * scale_factor);
     979    ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
     980    ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
     981    ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
     982    GrabMinSize = ImFloor(GrabMinSize * scale_factor);
     983    GrabRounding = ImFloor(GrabRounding * scale_factor);
     984    LogSliderDeadzone = ImFloor(LogSliderDeadzone * scale_factor);
     985    TabRounding = ImFloor(TabRounding * scale_factor);
     986    TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
     987    DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
     988    DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
     989    MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
    867990}
    868991
    869992ImGuiIO::ImGuiIO()
    870993{
    871    // Most fields are initialized with zero
    872    memset(this, 0, sizeof(*this));
    873 
    874    // Settings
    875    ConfigFlags = 0x00;
    876    BackendFlags = 0x00;
    877    DisplaySize = ImVec2(-1.0f, -1.0f);
    878    DeltaTime = 1.0f / 60.0f;
    879    IniSavingRate = 5.0f;
    880    IniFilename = "imgui.ini";
    881    LogFilename = "imgui_log.txt";
    882    MouseDoubleClickTime = 0.30f;
    883    MouseDoubleClickMaxDist = 6.0f;
    884    for (int i = 0; i < ImGuiKey_COUNT; i++)
    885       KeyMap[i] = -1;
    886    KeyRepeatDelay = 0.250f;
    887    KeyRepeatRate = 0.050f;
    888    UserData = NULL;
    889 
    890    Fonts = NULL;
    891    FontGlobalScale = 1.0f;
    892    FontDefault = NULL;
    893    FontAllowUserScaling = false;
    894    DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
    895    DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f);
    896 
    897    // Advanced/subtle behaviors
     994    // Most fields are initialized with zero
     995    memset(this, 0, sizeof(*this));
     996    IM_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Our pre-C++11 IM_STATIC_ASSERT() macros triggers warning on modern compilers so we don't use it here.
     997
     998    // Settings
     999    ConfigFlags = ImGuiConfigFlags_None;
     1000    BackendFlags = ImGuiBackendFlags_None;
     1001    DisplaySize = ImVec2(-1.0f, -1.0f);
     1002    DeltaTime = 1.0f / 60.0f;
     1003    IniSavingRate = 5.0f;
     1004    IniFilename = "imgui.ini";
     1005    LogFilename = "imgui_log.txt";
     1006    MouseDoubleClickTime = 0.30f;
     1007    MouseDoubleClickMaxDist = 6.0f;
     1008    for (int i = 0; i < ImGuiKey_COUNT; i++)
     1009        KeyMap[i] = -1;
     1010    KeyRepeatDelay = 0.275f;
     1011    KeyRepeatRate = 0.050f;
     1012    UserData = NULL;
     1013
     1014    Fonts = NULL;
     1015    FontGlobalScale = 1.0f;
     1016    FontDefault = NULL;
     1017    FontAllowUserScaling = false;
     1018    DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
     1019
     1020    // Miscellaneous options
     1021    MouseDrawCursor = false;
    8981022#ifdef __APPLE__
    899    OptMacOSXBehaviors = true;  // Set Mac OS X style defaults based on __APPLE__ compile time flag
     1023    ConfigMacOSXBehaviors = true;  // Set Mac OS X style defaults based on __APPLE__ compile time flag
    9001024#else
    901    OptMacOSXBehaviors = false;
     1025    ConfigMacOSXBehaviors = false;
    9021026#endif
    903    OptCursorBlink = true;
    904 
    905    // Settings (User Functions)
    906    GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations
    907    SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
    908    ClipboardUserData = NULL;
    909    ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
    910    ImeWindowHandle = NULL;
     1027    ConfigInputTextCursorBlink = true;
     1028    ConfigWindowsResizeFromEdges = true;
     1029    ConfigWindowsMoveFromTitleBarOnly = false;
     1030    ConfigWindowsMemoryCompactTimer = 60.0f;
     1031
     1032    // Platform Functions
     1033    BackendPlatformName = BackendRendererName = NULL;
     1034    BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
     1035    GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations
     1036    SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
     1037    ClipboardUserData = NULL;
     1038    ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
     1039    ImeWindowHandle = NULL;
    9111040
    9121041#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
    913    RenderDrawListsFn = NULL;
     1042    RenderDrawListsFn = NULL;
    9141043#endif
    9151044
    916    // Input (NB: we already have memset zero the entire structure)
    917    MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
    918    MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
    919    MouseDragThreshold = 6.0f;
    920    for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
    921    for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
    922    for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
     1045    // Input (NB: we already have memset zero the entire structure!)
     1046    MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
     1047    MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
     1048    MouseDragThreshold = 6.0f;
     1049    for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
     1050    for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
     1051    for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
    9231052}
    9241053
     
    9261055// - with glfw you can get those from the callback set in glfwSetCharCallback()
    9271056// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
    928 void ImGuiIO::AddInputCharacter(ImWchar c)
    929 {
    930    const int n = ImStrlenW(InputCharacters);
    931    if (n + 1 < IM_ARRAYSIZE(InputCharacters))
    932    {
    933       InputCharacters[n] = c;
    934       InputCharacters[n + 1] = '\0';
    935    }
     1057void ImGuiIO::AddInputCharacter(unsigned int c)
     1058{
     1059    if (c != 0)
     1060        InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
     1061}
     1062
     1063// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
     1064// we should save the high surrogate.
     1065void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
     1066{
     1067    if (c == 0 && InputQueueSurrogate == 0)
     1068        return;
     1069
     1070    if ((c & 0xFC00) == 0xD800) // High surrogate, must save
     1071    {
     1072        if (InputQueueSurrogate != 0)
     1073            InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
     1074        InputQueueSurrogate = c;
     1075        return;
     1076    }
     1077
     1078    ImWchar cp = c;
     1079    if (InputQueueSurrogate != 0)
     1080    {
     1081        if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate
     1082            InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
     1083        else if (IM_UNICODE_CODEPOINT_MAX == (0xFFFF)) // Codepoint will not fit in ImWchar (extra parenthesis around 0xFFFF somehow fixes -Wunreachable-code with Clang)
     1084            cp = IM_UNICODE_CODEPOINT_INVALID;
     1085        else
     1086            cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
     1087        InputQueueSurrogate = 0;
     1088    }
     1089    InputQueueCharacters.push_back(cp);
    9361090}
    9371091
    9381092void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
    9391093{
    940    // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more
    941    const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar);
    942    ImWchar wchars[wchars_buf_len];
    943    ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL);
    944    for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++)
    945       AddInputCharacter(wchars[i]);
     1094    while (*utf8_chars != 0)
     1095    {
     1096        unsigned int c = 0;
     1097        utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
     1098        if (c != 0)
     1099            InputQueueCharacters.push_back((ImWchar)c);
     1100    }
     1101}
     1102
     1103void ImGuiIO::ClearInputCharacters()
     1104{
     1105    InputQueueCharacters.resize(0);
    9461106}
    9471107
    9481108//-----------------------------------------------------------------------------
    949 // HELPERS
     1109// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
    9501110//-----------------------------------------------------------------------------
    9511111
    952 #define IM_F32_TO_INT8_UNBOUND(_VAL)    ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f)))   // Unsaturated, for display purpose
    953 #define IM_F32_TO_INT8_SAT(_VAL)        ((int)(ImSaturate(_VAL) * 255.0f + 0.5f))               // Saturated, always output 0..255
     1112ImVec2 ImBezierClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments)
     1113{
     1114    IM_ASSERT(num_segments > 0); // Use ImBezierClosestPointCasteljau()
     1115    ImVec2 p_last = p1;
     1116    ImVec2 p_closest;
     1117    float p_closest_dist2 = FLT_MAX;
     1118    float t_step = 1.0f / (float)num_segments;
     1119    for (int i_step = 1; i_step <= num_segments; i_step++)
     1120    {
     1121        ImVec2 p_current = ImBezierCalc(p1, p2, p3, p4, t_step * i_step);
     1122        ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
     1123        float dist2 = ImLengthSqr(p - p_line);
     1124        if (dist2 < p_closest_dist2)
     1125        {
     1126            p_closest = p_line;
     1127            p_closest_dist2 = dist2;
     1128        }
     1129        p_last = p_current;
     1130    }
     1131    return p_closest;
     1132}
     1133
     1134// Closely mimics PathBezierToCasteljau() in imgui_draw.cpp
     1135static void BezierClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
     1136{
     1137    float dx = x4 - x1;
     1138    float dy = y4 - y1;
     1139    float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
     1140    float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
     1141    d2 = (d2 >= 0) ? d2 : -d2;
     1142    d3 = (d3 >= 0) ? d3 : -d3;
     1143    if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
     1144    {
     1145        ImVec2 p_current(x4, y4);
     1146        ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
     1147        float dist2 = ImLengthSqr(p - p_line);
     1148        if (dist2 < p_closest_dist2)
     1149        {
     1150            p_closest = p_line;
     1151            p_closest_dist2 = dist2;
     1152        }
     1153        p_last = p_current;
     1154    }
     1155    else if (level < 10)
     1156    {
     1157        float x12 = (x1 + x2)*0.5f,       y12 = (y1 + y2)*0.5f;
     1158        float x23 = (x2 + x3)*0.5f,       y23 = (y2 + y3)*0.5f;
     1159        float x34 = (x3 + x4)*0.5f,       y34 = (y3 + y4)*0.5f;
     1160        float x123 = (x12 + x23)*0.5f,    y123 = (y12 + y23)*0.5f;
     1161        float x234 = (x23 + x34)*0.5f,    y234 = (y23 + y34)*0.5f;
     1162        float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
     1163        BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
     1164        BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
     1165    }
     1166}
     1167
     1168// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol
     1169// Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically.
     1170ImVec2 ImBezierClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol)
     1171{
     1172    IM_ASSERT(tess_tol > 0.0f);
     1173    ImVec2 p_last = p1;
     1174    ImVec2 p_closest;
     1175    float p_closest_dist2 = FLT_MAX;
     1176    BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0);
     1177    return p_closest;
     1178}
    9541179
    9551180ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
    9561181{
    957    ImVec2 ap = p - a;
    958    ImVec2 ab_dir = b - a;
    959    float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
    960    if (dot < 0.0f)
    961       return a;
    962    float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
    963    if (dot > ab_len_sqr)
    964       return b;
    965    return a + ab_dir * dot / ab_len_sqr;
     1182    ImVec2 ap = p - a;
     1183    ImVec2 ab_dir = b - a;
     1184    float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
     1185    if (dot < 0.0f)
     1186        return a;
     1187    float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
     1188    if (dot > ab_len_sqr)
     1189        return b;
     1190    return a + ab_dir * dot / ab_len_sqr;
    9661191}
    9671192
    9681193bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
    9691194{
    970    bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
    971    bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
    972    bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
    973    return ((b1 == b2) && (b2 == b3));
     1195    bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
     1196    bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
     1197    bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
     1198    return ((b1 == b2) && (b2 == b3));
    9741199}
    9751200
    9761201void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
    9771202{
    978    ImVec2 v0 = b - a;
    979    ImVec2 v1 = c - a;
    980    ImVec2 v2 = p - a;
    981    const float denom = v0.x * v1.y - v1.x * v0.y;
    982    out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
    983    out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
    984    out_u = 1.0f - out_v - out_w;
     1203    ImVec2 v0 = b - a;
     1204    ImVec2 v1 = c - a;
     1205    ImVec2 v2 = p - a;
     1206    const float denom = v0.x * v1.y - v1.x * v0.y;
     1207    out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
     1208    out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
     1209    out_u = 1.0f - out_v - out_w;
    9851210}
    9861211
    9871212ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
    9881213{
    989    ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
    990    ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
    991    ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
    992    float dist2_ab = ImLengthSqr(p - proj_ab);
    993    float dist2_bc = ImLengthSqr(p - proj_bc);
    994    float dist2_ca = ImLengthSqr(p - proj_ca);
    995    float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
    996    if (m == dist2_ab)
    997       return proj_ab;
    998    if (m == dist2_bc)
    999       return proj_bc;
    1000    return proj_ca;
    1001 }
    1002 
     1214    ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
     1215    ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
     1216    ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
     1217    float dist2_ab = ImLengthSqr(p - proj_ab);
     1218    float dist2_bc = ImLengthSqr(p - proj_bc);
     1219    float dist2_ca = ImLengthSqr(p - proj_ca);
     1220    float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
     1221    if (m == dist2_ab)
     1222        return proj_ab;
     1223    if (m == dist2_bc)
     1224        return proj_bc;
     1225    return proj_ca;
     1226}
     1227
     1228//-----------------------------------------------------------------------------
     1229// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions)
     1230//-----------------------------------------------------------------------------
     1231
     1232// Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more.
    10031233int ImStricmp(const char* str1, const char* str2)
    10041234{
    1005    int d;
    1006    while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
    1007    return d;
     1235    int d;
     1236    while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
     1237    return d;
    10081238}
    10091239
    10101240int ImStrnicmp(const char* str1, const char* str2, size_t count)
    10111241{
    1012    int d = 0;
    1013    while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
    1014    return d;
     1242    int d = 0;
     1243    while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
     1244    return d;
    10151245}
    10161246
    10171247void ImStrncpy(char* dst, const char* src, size_t count)
    10181248{
    1019    if (count < 1) return;
    1020    strncpy(dst, src, count);
    1021    dst[count - 1] = 0;
    1022 }
    1023 
    1024 char* ImStrdup(const char *str)
    1025 {
    1026    size_t len = strlen(str) + 1;
    1027    void* buf = ImGui::MemAlloc(len);
    1028    return (char*)memcpy(buf, (const void*)str, len);
     1249    if (count < 1)
     1250        return;
     1251    if (count > 1)
     1252        strncpy(dst, src, count - 1);
     1253    dst[count - 1] = 0;
     1254}
     1255
     1256char* ImStrdup(const char* str)
     1257{
     1258    size_t len = strlen(str);
     1259    void* buf = IM_ALLOC(len + 1);
     1260    return (char*)memcpy(buf, (const void*)str, len + 1);
     1261}
     1262
     1263char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
     1264{
     1265    size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
     1266    size_t src_size = strlen(src) + 1;
     1267    if (dst_buf_size < src_size)
     1268    {
     1269        IM_FREE(dst);
     1270        dst = (char*)IM_ALLOC(src_size);
     1271        if (p_dst_size)
     1272            *p_dst_size = src_size;
     1273    }
     1274    return (char*)memcpy(dst, (const void*)src, src_size);
    10291275}
    10301276
    10311277const char* ImStrchrRange(const char* str, const char* str_end, char c)
    10321278{
    1033    for (; str < str_end; str++)
    1034       if (*str == c)
    1035          return str;
    1036    return NULL;
     1279    const char* p = (const char*)memchr(str, (int)c, str_end - str);
     1280    return p;
    10371281}
    10381282
    10391283int ImStrlenW(const ImWchar* str)
    10401284{
    1041    int n = 0;
    1042    while (*str++) n++;
    1043    return n;
     1285    //return (int)wcslen((const wchar_t*)str);  // FIXME-OPT: Could use this when wchar_t are 16-bit
     1286    int n = 0;
     1287    while (*str++) n++;
     1288    return n;
     1289}
     1290
     1291// Find end-of-line. Return pointer will point to either first \n, either str_end.
     1292const char* ImStreolRange(const char* str, const char* str_end)
     1293{
     1294    const char* p = (const char*)memchr(str, '\n', str_end - str);
     1295    return p ? p : str_end;
    10441296}
    10451297
    10461298const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
    10471299{
    1048    while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
    1049       buf_mid_line--;
    1050    return buf_mid_line;
     1300    while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
     1301        buf_mid_line--;
     1302    return buf_mid_line;
    10511303}
    10521304
    10531305const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
    10541306{
    1055    if (!needle_end)
    1056       needle_end = needle + strlen(needle);
    1057 
    1058    const char un0 = (char)toupper(*needle);
    1059    while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
    1060    {
    1061       if (toupper(*haystack) == un0)
    1062       {
    1063          const char* b = needle + 1;
    1064          for (const char* a = haystack + 1; b < needle_end; a++, b++)
    1065             if (toupper(*a) != toupper(*b))
    1066                break;
    1067          if (b == needle_end)
    1068             return haystack;
    1069       }
    1070       haystack++;
    1071    }
    1072    return NULL;
    1073 }
    1074 
    1075 static const char* ImAtoi(const char* src, int* output)
    1076 {
    1077    int negative = 0;
    1078    if (*src == '-') { negative = 1; src++; }
    1079    if (*src == '+') { src++; }
    1080    int v = 0;
    1081    while (*src >= '0' && *src <= '9')
    1082       v = (v * 10) + (*src++ - '0');
    1083    *output = negative ? -v : v;
    1084    return src;
    1085 }
    1086 
    1087 // A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
     1307    if (!needle_end)
     1308        needle_end = needle + strlen(needle);
     1309
     1310    const char un0 = (char)toupper(*needle);
     1311    while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
     1312    {
     1313        if (toupper(*haystack) == un0)
     1314        {
     1315            const char* b = needle + 1;
     1316            for (const char* a = haystack + 1; b < needle_end; a++, b++)
     1317                if (toupper(*a) != toupper(*b))
     1318                    break;
     1319            if (b == needle_end)
     1320                return haystack;
     1321        }
     1322        haystack++;
     1323    }
     1324    return NULL;
     1325}
     1326
     1327// 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.
     1328void ImStrTrimBlanks(char* buf)
     1329{
     1330    char* p = buf;
     1331    while (p[0] == ' ' || p[0] == '\t')     // Leading blanks
     1332        p++;
     1333    char* p_start = p;
     1334    while (*p != 0)                         // Find end of string
     1335        p++;
     1336    while (p > p_start && (p[-1] == ' ' || p[-1] == '\t'))  // Trailing blanks
     1337        p--;
     1338    if (p_start != buf)                     // Copy memory if we had leading blanks
     1339        memmove(buf, p_start, p - p_start);
     1340    buf[p - p_start] = 0;                   // Zero terminate
     1341}
     1342
     1343const char* ImStrSkipBlank(const char* str)
     1344{
     1345    while (str[0] == ' ' || str[0] == '\t')
     1346        str++;
     1347    return str;
     1348}
     1349
     1350// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
    10881351// 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.
    10891352// B) When buf==NULL vsnprintf() will return the output size.
    1090 #ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
     1353#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
     1354
     1355// We support stb_sprintf which is much faster (see: https://github.com/nothings/stb/blob/master/stb_sprintf.h)
     1356// You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
     1357// and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are
     1358// designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.)
     1359#ifdef IMGUI_USE_STB_SPRINTF
     1360#define STB_SPRINTF_IMPLEMENTATION
     1361#include "stb_sprintf.h"
     1362#endif
     1363
     1364#if defined(_MSC_VER) && !defined(vsnprintf)
     1365#define vsnprintf _vsnprintf
     1366#endif
     1367
    10911368int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
    10921369{
    1093    va_list args;
    1094    va_start(args, fmt);
    1095    int w = vsnprintf(buf, buf_size, fmt, args);
    1096    va_end(args);
    1097    if (buf == NULL)
    1098       return w;
    1099    if (w == -1 || w >= (int)buf_size)
    1100       w = (int)buf_size - 1;
    1101    buf[w] = 0;
    1102    return w;
     1370    va_list args;
     1371    va_start(args, fmt);
     1372#ifdef IMGUI_USE_STB_SPRINTF
     1373    int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
     1374#else
     1375    int w = vsnprintf(buf, buf_size, fmt, args);
     1376#endif
     1377    va_end(args);
     1378    if (buf == NULL)
     1379        return w;
     1380    if (w == -1 || w >= (int)buf_size)
     1381        w = (int)buf_size - 1;
     1382    buf[w] = 0;
     1383    return w;
    11031384}
    11041385
    11051386int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
    11061387{
    1107    int w = vsnprintf(buf, buf_size, fmt, args);
    1108    if (buf == NULL)
    1109       return w;
    1110    if (w == -1 || w >= (int)buf_size)
    1111       w = (int)buf_size - 1;
    1112    buf[w] = 0;
    1113    return w;
    1114 }
    1115 #endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
    1116 
    1117 // Pass data_size==0 for zero-terminated strings
     1388#ifdef IMGUI_USE_STB_SPRINTF
     1389    int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
     1390#else
     1391    int w = vsnprintf(buf, buf_size, fmt, args);
     1392#endif
     1393    if (buf == NULL)
     1394        return w;
     1395    if (w == -1 || w >= (int)buf_size)
     1396        w = (int)buf_size - 1;
     1397    buf[w] = 0;
     1398    return w;
     1399}
     1400#endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
     1401
     1402// CRC32 needs a 1KB lookup table (not cache friendly)
     1403// Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
     1404// - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
     1405static const ImU32 GCrc32LookupTable[256] =
     1406{
     1407    0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
     1408    0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
     1409    0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
     1410    0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
     1411    0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
     1412    0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
     1413    0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
     1414    0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
     1415    0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
     1416    0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
     1417    0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
     1418    0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
     1419    0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
     1420    0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
     1421    0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
     1422    0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
     1423};
     1424
     1425// Known size hash
     1426// It is ok to call ImHashData on a string with known length but the ### operator won't be supported.
    11181427// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
    1119 ImU32 ImHash(const void* data, int data_size, ImU32 seed)
    1120 {
    1121    static ImU32 crc32_lut[256] = { 0 };
    1122    if (!crc32_lut[1])
    1123    {
    1124       const ImU32 polynomial = 0xEDB88320;
    1125       for (ImU32 i = 0; i < 256; i++)
    1126       {
    1127          ImU32 crc = i;
    1128          for (ImU32 j = 0; j < 8; j++)
    1129             crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
    1130          crc32_lut[i] = crc;
    1131       }
    1132    }
    1133 
    1134    seed = ~seed;
    1135    ImU32 crc = seed;
    1136    const unsigned char* current = (const unsigned char*)data;
    1137 
    1138    if (data_size > 0)
    1139    {
    1140       // Known size
    1141       while (data_size--)
    1142          crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
    1143    }
    1144    else
    1145    {
    1146       // Zero-terminated string
    1147       while (unsigned char c = *current++)
    1148       {
    1149          // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
    1150          // Because this syntax is rarely used we are optimizing for the common case.
    1151          // - If we reach ### in the string we discard the hash so far and reset to the seed.
    1152          // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
    1153          if (c == '#' && current[0] == '#' && current[1] == '#')
    1154             crc = seed;
    1155          crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
    1156       }
    1157    }
    1158    return ~crc;
     1428ImU32 ImHashData(const void* data_p, size_t data_size, ImU32 seed)
     1429{
     1430    ImU32 crc = ~seed;
     1431    const unsigned char* data = (const unsigned char*)data_p;
     1432    const ImU32* crc32_lut = GCrc32LookupTable;
     1433    while (data_size-- != 0)
     1434        crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
     1435    return ~crc;
     1436}
     1437
     1438// Zero-terminated string hash, with support for ### to reset back to seed value
     1439// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
     1440// Because this syntax is rarely used we are optimizing for the common case.
     1441// - If we reach ### in the string we discard the hash so far and reset to the seed.
     1442// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build)
     1443// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
     1444ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed)
     1445{
     1446    seed = ~seed;
     1447    ImU32 crc = seed;
     1448    const unsigned char* data = (const unsigned char*)data_p;
     1449    const ImU32* crc32_lut = GCrc32LookupTable;
     1450    if (data_size != 0)
     1451    {
     1452        while (data_size-- != 0)
     1453        {
     1454            unsigned char c = *data++;
     1455            if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#')
     1456                crc = seed;
     1457            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
     1458        }
     1459    }
     1460    else
     1461    {
     1462        while (unsigned char c = *data++)
     1463        {
     1464            if (c == '#' && data[0] == '#' && data[1] == '#')
     1465                crc = seed;
     1466            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
     1467        }
     1468    }
     1469    return ~crc;
    11591470}
    11601471
    11611472//-----------------------------------------------------------------------------
    1162 // ImText* helpers
     1473// [SECTION] MISC HELPERS/UTILITIES (File functions)
    11631474//-----------------------------------------------------------------------------
    11641475
    1165 // Convert UTF-8 to 32-bits character, process single character input.
     1476// Default file functions
     1477#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
     1478
     1479ImFileHandle ImFileOpen(const char* filename, const char* mode)
     1480{
     1481#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
     1482    // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames.
     1483    // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32!
     1484    const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
     1485    const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
     1486    ImVector<ImWchar> buf;
     1487    buf.resize(filename_wsize + mode_wsize);
     1488    ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize);
     1489    ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize);
     1490    return ::_wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]);
     1491#else
     1492    return fopen(filename, mode);
     1493#endif
     1494}
     1495
     1496// We should in theory be using fseeko()/ftello() with off_t and _fseeki64()/_ftelli64() with __int64, waiting for the PR that does that in a very portable pre-C++11 zero-warnings way.
     1497bool    ImFileClose(ImFileHandle f)     { return fclose(f) == 0; }
     1498ImU64   ImFileGetSize(ImFileHandle f)   { long off = 0, sz = 0; return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET)) ? (ImU64)sz : (ImU64)-1; }
     1499ImU64   ImFileRead(void* data, ImU64 sz, ImU64 count, ImFileHandle f)           { return fread(data, (size_t)sz, (size_t)count, f); }
     1500ImU64   ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f)    { return fwrite(data, (size_t)sz, (size_t)count, f); }
     1501#endif // #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
     1502
     1503// Helper: Load file content into memory
     1504// Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree()
     1505// This can't really be used with "rt" because fseek size won't match read size.
     1506void*   ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes)
     1507{
     1508    IM_ASSERT(filename && mode);
     1509    if (out_file_size)
     1510        *out_file_size = 0;
     1511
     1512    ImFileHandle f;
     1513    if ((f = ImFileOpen(filename, mode)) == NULL)
     1514        return NULL;
     1515
     1516    size_t file_size = (size_t)ImFileGetSize(f);
     1517    if (file_size == (size_t)-1)
     1518    {
     1519        ImFileClose(f);
     1520        return NULL;
     1521    }
     1522
     1523    void* file_data = IM_ALLOC(file_size + padding_bytes);
     1524    if (file_data == NULL)
     1525    {
     1526        ImFileClose(f);
     1527        return NULL;
     1528    }
     1529    if (ImFileRead(file_data, 1, file_size, f) != file_size)
     1530    {
     1531        ImFileClose(f);
     1532        IM_FREE(file_data);
     1533        return NULL;
     1534    }
     1535    if (padding_bytes > 0)
     1536        memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
     1537
     1538    ImFileClose(f);
     1539    if (out_file_size)
     1540        *out_file_size = file_size;
     1541
     1542    return file_data;
     1543}
     1544
     1545//-----------------------------------------------------------------------------
     1546// [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
     1547//-----------------------------------------------------------------------------
     1548
     1549// Convert UTF-8 to 32-bit character, process single character input.
    11661550// Based on stb_from_utf8() from github.com/nothings/stb/
    11671551// We handle UTF-8 decoding error by skipping forward.
    11681552int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
    11691553{
    1170    unsigned int c = (unsigned int)-1;
    1171    const unsigned char* str = (const unsigned char*)in_text;
    1172    if (!(*str & 0x80))
    1173    {
    1174       c = (unsigned int)(*str++);
    1175       *out_char = c;
    1176       return 1;
    1177    }
    1178    if ((*str & 0xe0) == 0xc0)
    1179    {
    1180       *out_char = 0xFFFD; // will be invalid but not end of string
    1181       if (in_text_end && in_text_end - (const char*)str < 2) return 1;
    1182       if (*str < 0xc2) return 2;
    1183       c = (unsigned int)((*str++ & 0x1f) << 6);
    1184       if ((*str & 0xc0) != 0x80) return 2;
    1185       c += (*str++ & 0x3f);
    1186       *out_char = c;
    1187       return 2;
    1188    }
    1189    if ((*str & 0xf0) == 0xe0)
    1190    {
    1191       *out_char = 0xFFFD; // will be invalid but not end of string
    1192       if (in_text_end && in_text_end - (const char*)str < 3) return 1;
    1193       if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
    1194       if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
    1195       c = (unsigned int)((*str++ & 0x0f) << 12);
    1196       if ((*str & 0xc0) != 0x80) return 3;
    1197       c += (unsigned int)((*str++ & 0x3f) << 6);
    1198       if ((*str & 0xc0) != 0x80) return 3;
    1199       c += (*str++ & 0x3f);
    1200       *out_char = c;
    1201       return 3;
    1202    }
    1203    if ((*str & 0xf8) == 0xf0)
    1204    {
    1205       *out_char = 0xFFFD; // will be invalid but not end of string
    1206       if (in_text_end && in_text_end - (const char*)str < 4) return 1;
    1207       if (*str > 0xf4) return 4;
    1208       if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
    1209       if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
    1210       c = (unsigned int)((*str++ & 0x07) << 18);
    1211       if ((*str & 0xc0) != 0x80) return 4;
    1212       c += (unsigned int)((*str++ & 0x3f) << 12);
    1213       if ((*str & 0xc0) != 0x80) return 4;
    1214       c += (unsigned int)((*str++ & 0x3f) << 6);
    1215       if ((*str & 0xc0) != 0x80) return 4;
    1216       c += (*str++ & 0x3f);
    1217       // utf-8 encodings of values used in surrogate pairs are invalid
    1218       if ((c & 0xFFFFF800) == 0xD800) return 4;
    1219       *out_char = c;
    1220       return 4;
    1221    }
    1222    *out_char = 0;
    1223    return 0;
     1554    unsigned int c = (unsigned int)-1;
     1555    const unsigned char* str = (const unsigned char*)in_text;
     1556    if (!(*str & 0x80))
     1557    {
     1558        c = (unsigned int)(*str++);
     1559        *out_char = c;
     1560        return 1;
     1561    }
     1562    if ((*str & 0xe0) == 0xc0)
     1563    {
     1564        *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string
     1565        if (in_text_end && in_text_end - (const char*)str < 2) return 1;
     1566        if (*str < 0xc2) return 2;
     1567        c = (unsigned int)((*str++ & 0x1f) << 6);
     1568        if ((*str & 0xc0) != 0x80) return 2;
     1569        c += (*str++ & 0x3f);
     1570        *out_char = c;
     1571        return 2;
     1572    }
     1573    if ((*str & 0xf0) == 0xe0)
     1574    {
     1575        *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string
     1576        if (in_text_end && in_text_end - (const char*)str < 3) return 1;
     1577        if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
     1578        if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
     1579        c = (unsigned int)((*str++ & 0x0f) << 12);
     1580        if ((*str & 0xc0) != 0x80) return 3;
     1581        c += (unsigned int)((*str++ & 0x3f) << 6);
     1582        if ((*str & 0xc0) != 0x80) return 3;
     1583        c += (*str++ & 0x3f);
     1584        *out_char = c;
     1585        return 3;
     1586    }
     1587    if ((*str & 0xf8) == 0xf0)
     1588    {
     1589        *out_char = IM_UNICODE_CODEPOINT_INVALID; // will be invalid but not end of string
     1590        if (in_text_end && in_text_end - (const char*)str < 4) return 1;
     1591        if (*str > 0xf4) return 4;
     1592        if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
     1593        if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
     1594        c = (unsigned int)((*str++ & 0x07) << 18);
     1595        if ((*str & 0xc0) != 0x80) return 4;
     1596        c += (unsigned int)((*str++ & 0x3f) << 12);
     1597        if ((*str & 0xc0) != 0x80) return 4;
     1598        c += (unsigned int)((*str++ & 0x3f) << 6);
     1599        if ((*str & 0xc0) != 0x80) return 4;
     1600        c += (*str++ & 0x3f);
     1601        // utf-8 encodings of values used in surrogate pairs are invalid
     1602        if ((c & 0xFFFFF800) == 0xD800) return 4;
     1603        // If codepoint does not fit in ImWchar, use replacement character U+FFFD instead
     1604        if (c > IM_UNICODE_CODEPOINT_MAX) c = IM_UNICODE_CODEPOINT_INVALID;
     1605        *out_char = c;
     1606        return 4;
     1607    }
     1608    *out_char = 0;
     1609    return 0;
    12241610}
    12251611
    12261612int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
    12271613{
    1228    ImWchar* buf_out = buf;
    1229    ImWchar* buf_end = buf + buf_size;
    1230    while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
    1231    {
    1232       unsigned int c;
    1233       in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
    1234       if (c == 0)
    1235          break;
    1236       if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes
    1237          *buf_out++ = (ImWchar)c;
    1238    }
    1239    *buf_out = 0;
    1240    if (in_text_remaining)
    1241       *in_text_remaining = in_text;
    1242    return (int)(buf_out - buf);
     1614    ImWchar* buf_out = buf;
     1615    ImWchar* buf_end = buf + buf_size;
     1616    while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
     1617    {
     1618        unsigned int c;
     1619        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
     1620        if (c == 0)
     1621            break;
     1622        *buf_out++ = (ImWchar)c;
     1623    }
     1624    *buf_out = 0;
     1625    if (in_text_remaining)
     1626        *in_text_remaining = in_text;
     1627    return (int)(buf_out - buf);
    12431628}
    12441629
    12451630int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
    12461631{
    1247    int char_count = 0;
    1248    while ((!in_text_end || in_text < in_text_end) && *in_text)
    1249    {
    1250       unsigned int c;
    1251       in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
    1252       if (c == 0)
    1253          break;
    1254       if (c < 0x10000)
    1255          char_count++;
    1256    }
    1257    return char_count;
     1632    int char_count = 0;
     1633    while ((!in_text_end || in_text < in_text_end) && *in_text)
     1634    {
     1635        unsigned int c;
     1636        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
     1637        if (c == 0)
     1638            break;
     1639        char_count++;
     1640    }
     1641    return char_count;
    12581642}
    12591643
     
    12611645static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
    12621646{
    1263    if (c < 0x80)
    1264    {
    1265       buf[0] = (char)c;
    1266       return 1;
    1267    }
    1268    if (c < 0x800)
    1269    {
    1270       if (buf_size < 2) return 0;
    1271       buf[0] = (char)(0xc0 + (c >> 6));
    1272       buf[1] = (char)(0x80 + (c & 0x3f));
    1273       return 2;
    1274    }
    1275    if (c >= 0xdc00 && c < 0xe000)
    1276    {
    1277       return 0;
    1278    }
    1279    if (c >= 0xd800 && c < 0xdc00)
    1280    {
    1281       if (buf_size < 4) return 0;
    1282       buf[0] = (char)(0xf0 + (c >> 18));
    1283       buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
    1284       buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
    1285       buf[3] = (char)(0x80 + ((c) & 0x3f));
    1286       return 4;
    1287    }
    1288    //else if (c < 0x10000)
    1289    {
    1290       if (buf_size < 3) return 0;
    1291       buf[0] = (char)(0xe0 + (c >> 12));
    1292       buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
    1293       buf[2] = (char)(0x80 + ((c) & 0x3f));
    1294       return 3;
    1295    }
     1647    if (c < 0x80)
     1648    {
     1649        buf[0] = (char)c;
     1650        return 1;
     1651    }
     1652    if (c < 0x800)
     1653    {
     1654        if (buf_size < 2) return 0;
     1655        buf[0] = (char)(0xc0 + (c >> 6));
     1656        buf[1] = (char)(0x80 + (c & 0x3f));
     1657        return 2;
     1658    }
     1659    if (c < 0x10000)
     1660    {
     1661        if (buf_size < 3) return 0;
     1662        buf[0] = (char)(0xe0 + (c >> 12));
     1663        buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
     1664        buf[2] = (char)(0x80 + ((c ) & 0x3f));
     1665        return 3;
     1666    }
     1667    if (c <= 0x10FFFF)
     1668    {
     1669        if (buf_size < 4) return 0;
     1670        buf[0] = (char)(0xf0 + (c >> 18));
     1671        buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
     1672        buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
     1673        buf[3] = (char)(0x80 + ((c ) & 0x3f));
     1674        return 4;
     1675    }
     1676    // Invalid code point, the max unicode is 0x10FFFF
     1677    return 0;
     1678}
     1679
     1680// Not optimal but we very rarely use this function.
     1681int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
     1682{
     1683    unsigned int unused = 0;
     1684    return ImTextCharFromUtf8(&unused, in_text, in_text_end);
    12961685}
    12971686
    12981687static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
    12991688{
    1300    if (c < 0x80) return 1;
    1301    if (c < 0x800) return 2;
    1302    if (c >= 0xdc00 && c < 0xe000) return 0;
    1303    if (c >= 0xd800 && c < 0xdc00) return 4;
    1304    return 3;
     1689    if (c < 0x80) return 1;
     1690    if (c < 0x800) return 2;
     1691    if (c < 0x10000) return 3;
     1692    if (c <= 0x10FFFF) return 4;
     1693    return 3;
    13051694}
    13061695
    13071696int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
    13081697{
    1309    char* buf_out = buf;
    1310    const char* buf_end = buf + buf_size;
    1311    while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
    1312    {
    1313       unsigned int c = (unsigned int)(*in_text++);
    1314       if (c < 0x80)
    1315          *buf_out++ = (char)c;
    1316       else
    1317          buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c);
    1318    }
    1319    *buf_out = 0;
    1320    return (int)(buf_out - buf);
     1698    char* buf_out = buf;
     1699    const char* buf_end = buf + buf_size;
     1700    while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
     1701    {
     1702        unsigned int c = (unsigned int)(*in_text++);
     1703        if (c < 0x80)
     1704            *buf_out++ = (char)c;
     1705        else
     1706            buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c);
     1707    }
     1708    *buf_out = 0;
     1709    return (int)(buf_out - buf);
    13211710}
    13221711
    13231712int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
    13241713{
    1325    int bytes_count = 0;
    1326    while ((!in_text_end || in_text < in_text_end) && *in_text)
    1327    {
    1328       unsigned int c = (unsigned int)(*in_text++);
    1329       if (c < 0x80)
    1330          bytes_count++;
    1331       else
    1332          bytes_count += ImTextCountUtf8BytesFromChar(c);
    1333    }
    1334    return bytes_count;
     1714    int bytes_count = 0;
     1715    while ((!in_text_end || in_text < in_text_end) && *in_text)
     1716    {
     1717        unsigned int c = (unsigned int)(*in_text++);
     1718        if (c < 0x80)
     1719            bytes_count++;
     1720        else
     1721            bytes_count += ImTextCountUtf8BytesFromChar(c);
     1722    }
     1723    return bytes_count;
     1724}
     1725
     1726//-----------------------------------------------------------------------------
     1727// [SECTION] MISC HELPERS/UTILITIES (Color functions)
     1728// Note: The Convert functions are early design which are not consistent with other API.
     1729//-----------------------------------------------------------------------------
     1730
     1731IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b)
     1732{
     1733    float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
     1734    int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);
     1735    int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);
     1736    int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);
     1737    return IM_COL32(r, g, b, 0xFF);
    13351738}
    13361739
    13371740ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
    13381741{
    1339    float s = 1.0f / 255.0f;
    1340    return ImVec4(
    1341       ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
    1342       ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
    1343       ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
    1344       ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
     1742    float s = 1.0f / 255.0f;
     1743    return ImVec4(
     1744        ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
     1745        ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
     1746        ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
     1747        ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
    13451748}
    13461749
    13471750ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
    13481751{
    1349    ImU32 out;
    1350    out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
    1351    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
    1352    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
    1353    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
    1354    return out;
    1355 }
    1356 
    1357 ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
    1358 {
    1359    ImGuiStyle& style = GImGui->Style;
    1360    ImVec4 c = style.Colors[idx];
    1361    c.w *= style.Alpha * alpha_mul;
    1362    return ColorConvertFloat4ToU32(c);
    1363 }
    1364 
    1365 ImU32 ImGui::GetColorU32(const ImVec4& col)
    1366 {
    1367    ImGuiStyle& style = GImGui->Style;
    1368    ImVec4 c = col;
    1369    c.w *= style.Alpha;
    1370    return ColorConvertFloat4ToU32(c);
    1371 }
    1372 
    1373 const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
    1374 {
    1375    ImGuiStyle& style = GImGui->Style;
    1376    return style.Colors[idx];
    1377 }
    1378 
    1379 ImU32 ImGui::GetColorU32(ImU32 col)
    1380 {
    1381    float style_alpha = GImGui->Style.Alpha;
    1382    if (style_alpha >= 1.0f)
    1383       return col;
    1384    ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
    1385    a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
    1386    return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
     1752    ImU32 out;
     1753    out  = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
     1754    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
     1755    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
     1756    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
     1757    return out;
    13871758}
    13881759
     
    13911762void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
    13921763{
    1393    float K = 0.f;
    1394    if (g < b)
    1395    {
    1396       ImSwap(g, b);
    1397       K = -1.f;
    1398    }
    1399    if (r < g)
    1400    {
    1401       ImSwap(r, g);
    1402       K = -2.f / 6.f - K;
    1403    }
    1404 
    1405    const float chroma = r - (g < b ? g : b);
    1406    out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));
    1407    out_s = chroma / (r + 1e-20f);
    1408    out_v = r;
     1764    float K = 0.f;
     1765    if (g < b)
     1766    {
     1767        ImSwap(g, b);
     1768        K = -1.f;
     1769    }
     1770    if (r < g)
     1771    {
     1772        ImSwap(r, g);
     1773        K = -2.f / 6.f - K;
     1774    }
     1775
     1776    const float chroma = r - (g < b ? g : b);
     1777    out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
     1778    out_s = chroma / (r + 1e-20f);
     1779    out_v = r;
    14091780}
    14101781
     
    14131784void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
    14141785{
    1415    if (s == 0.0f)
    1416    {
    1417       // gray
    1418       out_r = out_g = out_b = v;
    1419       return;
    1420    }
    1421 
    1422    h = fmodf(h, 1.0f) / (60.0f / 360.0f);
    1423    int   i = (int)h;
    1424    float f = h - (float)i;
    1425    float p = v * (1.0f - s);
    1426    float q = v * (1.0f - s * f);
    1427    float t = v * (1.0f - s * (1.0f - f));
    1428 
    1429    switch (i)
    1430    {
    1431    case 0: out_r = v; out_g = t; out_b = p; break;
    1432    case 1: out_r = q; out_g = v; out_b = p; break;
    1433    case 2: out_r = p; out_g = v; out_b = t; break;
    1434    case 3: out_r = p; out_g = q; out_b = v; break;
    1435    case 4: out_r = t; out_g = p; out_b = v; break;
    1436    case 5: default: out_r = v; out_g = p; out_b = q; break;
    1437    }
    1438 }
    1439 
    1440 FILE* ImFileOpen(const char* filename, const char* mode)
    1441 {
    1442 #if defined(_WIN32) && !defined(__CYGWIN__)
    1443    // 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)
    1444    const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
    1445    const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
    1446    ImVector<ImWchar> buf;
    1447    buf.resize(filename_wsize + mode_wsize);
    1448    ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
    1449    ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
    1450    return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
    1451 #else
    1452    return fopen(filename, mode);
    1453 #endif
    1454 }
    1455 
    1456 // Load file content into memory
    1457 // Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
    1458 void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes)
    1459 {
    1460    IM_ASSERT(filename && file_open_mode);
    1461    if (out_file_size)
    1462       *out_file_size = 0;
    1463 
    1464    FILE* f;
    1465    if ((f = ImFileOpen(filename, file_open_mode)) == NULL)
    1466       return NULL;
    1467 
    1468    long file_size_signed;
    1469    if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
    1470    {
    1471       fclose(f);
    1472       return NULL;
    1473    }
    1474 
    1475    int file_size = (int)file_size_signed;
    1476    void* file_data = ImGui::MemAlloc((size_t)(file_size + padding_bytes));
    1477    if (file_data == NULL)
    1478    {
    1479       fclose(f);
    1480       return NULL;
    1481    }
    1482    if (fread(file_data, 1, (size_t)file_size, f) != (size_t)file_size)
    1483    {
    1484       fclose(f);
    1485       ImGui::MemFree(file_data);
    1486       return NULL;
    1487    }
    1488    if (padding_bytes > 0)
    1489       memset((void *)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
    1490 
    1491    fclose(f);
    1492    if (out_file_size)
    1493       *out_file_size = file_size;
    1494 
    1495    return file_data;
     1786    if (s == 0.0f)
     1787    {
     1788        // gray
     1789        out_r = out_g = out_b = v;
     1790        return;
     1791    }
     1792
     1793    h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
     1794    int   i = (int)h;
     1795    float f = h - (float)i;
     1796    float p = v * (1.0f - s);
     1797    float q = v * (1.0f - s * f);
     1798    float t = v * (1.0f - s * (1.0f - f));
     1799
     1800    switch (i)
     1801    {
     1802    case 0: out_r = v; out_g = t; out_b = p; break;
     1803    case 1: out_r = q; out_g = v; out_b = p; break;
     1804    case 2: out_r = p; out_g = v; out_b = t; break;
     1805    case 3: out_r = p; out_g = q; out_b = v; break;
     1806    case 4: out_r = t; out_g = p; out_b = v; break;
     1807    case 5: default: out_r = v; out_g = p; out_b = q; break;
     1808    }
    14961809}
    14971810
    14981811//-----------------------------------------------------------------------------
    1499 // ImGuiStorage
     1812// [SECTION] ImGuiStorage
    15001813// Helper: Key->value storage
    15011814//-----------------------------------------------------------------------------
    15021815
    15031816// std::lower_bound but without the bullshit
    1504 static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::Pair>& data, ImGuiID key)
    1505 {
    1506    ImVector<ImGuiStorage::Pair>::iterator first = data.begin();
    1507    ImVector<ImGuiStorage::Pair>::iterator last = data.end();
    1508    size_t count = (size_t)(last - first);
    1509    while (count > 0)
    1510    {
    1511       size_t count2 = count >> 1;
    1512       ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
    1513       if (mid->key < key)
    1514       {
    1515          first = ++mid;
    1516          count -= count2 + 1;
    1517       }
    1518       else
    1519       {
    1520          count = count2;
    1521       }
    1522    }
    1523    return first;
     1817static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key)
     1818{
     1819    ImGuiStorage::ImGuiStoragePair* first = data.Data;
     1820    ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size;
     1821    size_t count = (size_t)(last - first);
     1822    while (count > 0)
     1823    {
     1824        size_t count2 = count >> 1;
     1825        ImGuiStorage::ImGuiStoragePair* mid = first + count2;
     1826        if (mid->key < key)
     1827        {
     1828            first = ++mid;
     1829            count -= count2 + 1;
     1830        }
     1831        else
     1832        {
     1833            count = count2;
     1834        }
     1835    }
     1836    return first;
    15241837}
    15251838
     
    15271840void ImGuiStorage::BuildSortByKey()
    15281841{
    1529    struct StaticFunc
    1530    {
    1531       static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
    1532       {
    1533          // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
    1534          if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1;
    1535          if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1;
    1536          return 0;
    1537       }
    1538    };
    1539    if (Data.Size > 1)
    1540       qsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID);
     1842    struct StaticFunc
     1843    {
     1844        static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
     1845        {
     1846            // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
     1847            if (((const ImGuiStoragePair*)lhs)->key > ((const ImGuiStoragePair*)rhs)->key) return +1;
     1848            if (((const ImGuiStoragePair*)lhs)->key < ((const ImGuiStoragePair*)rhs)->key) return -1;
     1849            return 0;
     1850        }
     1851    };
     1852    if (Data.Size > 1)
     1853        ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), StaticFunc::PairCompareByID);
    15411854}
    15421855
    15431856int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
    15441857{
    1545    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    1546    if (it == Data.end() || it->key != key)
    1547       return default_val;
    1548    return it->val_i;
     1858    ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
     1859    if (it == Data.end() || it->key != key)
     1860        return default_val;
     1861    return it->val_i;
    15491862}
    15501863
    15511864bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
    15521865{
    1553    return GetInt(key, default_val ? 1 : 0) != 0;
     1866    return GetInt(key, default_val ? 1 : 0) != 0;
    15541867}
    15551868
    15561869float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
    15571870{
    1558    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    1559    if (it == Data.end() || it->key != key)
    1560       return default_val;
    1561    return it->val_f;
     1871    ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
     1872    if (it == Data.end() || it->key != key)
     1873        return default_val;
     1874    return it->val_f;
    15621875}
    15631876
    15641877void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
    15651878{
    1566    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    1567    if (it == Data.end() || it->key != key)
    1568       return NULL;
    1569    return it->val_p;
     1879    ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
     1880    if (it == Data.end() || it->key != key)
     1881        return NULL;
     1882    return it->val_p;
    15701883}
    15711884
     
    15731886int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
    15741887{
    1575    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1576    if (it == Data.end() || it->key != key)
    1577       it = Data.insert(it, Pair(key, default_val));
    1578    return &it->val_i;
     1888    ImGuiStoragePair* it = LowerBound(Data, key);
     1889    if (it == Data.end() || it->key != key)
     1890        it = Data.insert(it, ImGuiStoragePair(key, default_val));
     1891    return &it->val_i;
    15791892}
    15801893
    15811894bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
    15821895{
    1583    return (bool*)GetIntRef(key, default_val ? 1 : 0);
     1896    return (bool*)GetIntRef(key, default_val ? 1 : 0);
    15841897}
    15851898
    15861899float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
    15871900{
    1588    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1589    if (it == Data.end() || it->key != key)
    1590       it = Data.insert(it, Pair(key, default_val));
    1591    return &it->val_f;
     1901    ImGuiStoragePair* it = LowerBound(Data, key);
     1902    if (it == Data.end() || it->key != key)
     1903        it = Data.insert(it, ImGuiStoragePair(key, default_val));
     1904    return &it->val_f;
    15921905}
    15931906
    15941907void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
    15951908{
    1596    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1597    if (it == Data.end() || it->key != key)
    1598       it = Data.insert(it, Pair(key, default_val));
    1599    return &it->val_p;
     1909    ImGuiStoragePair* it = LowerBound(Data, key);
     1910    if (it == Data.end() || it->key != key)
     1911        it = Data.insert(it, ImGuiStoragePair(key, default_val));
     1912    return &it->val_p;
    16001913}
    16011914
     
    16031916void ImGuiStorage::SetInt(ImGuiID key, int val)
    16041917{
    1605    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1606    if (it == Data.end() || it->key != key)
    1607    {
    1608       Data.insert(it, Pair(key, val));
    1609       return;
    1610    }
    1611    it->val_i = val;
     1918    ImGuiStoragePair* it = LowerBound(Data, key);
     1919    if (it == Data.end() || it->key != key)
     1920    {
     1921        Data.insert(it, ImGuiStoragePair(key, val));
     1922        return;
     1923    }
     1924    it->val_i = val;
    16121925}
    16131926
    16141927void ImGuiStorage::SetBool(ImGuiID key, bool val)
    16151928{
    1616    SetInt(key, val ? 1 : 0);
     1929    SetInt(key, val ? 1 : 0);
    16171930}
    16181931
    16191932void ImGuiStorage::SetFloat(ImGuiID key, float val)
    16201933{
    1621    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1622    if (it == Data.end() || it->key != key)
    1623    {
    1624       Data.insert(it, Pair(key, val));
    1625       return;
    1626    }
    1627    it->val_f = val;
     1934    ImGuiStoragePair* it = LowerBound(Data, key);
     1935    if (it == Data.end() || it->key != key)
     1936    {
     1937        Data.insert(it, ImGuiStoragePair(key, val));
     1938        return;
     1939    }
     1940    it->val_f = val;
    16281941}
    16291942
    16301943void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
    16311944{
    1632    ImVector<Pair>::iterator it = LowerBound(Data, key);
    1633    if (it == Data.end() || it->key != key)
    1634    {
    1635       Data.insert(it, Pair(key, val));
    1636       return;
    1637    }
    1638    it->val_p = val;
     1945    ImGuiStoragePair* it = LowerBound(Data, key);
     1946    if (it == Data.end() || it->key != key)
     1947    {
     1948        Data.insert(it, ImGuiStoragePair(key, val));
     1949        return;
     1950    }
     1951    it->val_p = val;
    16391952}
    16401953
    16411954void ImGuiStorage::SetAllInt(int v)
    16421955{
    1643    for (int i = 0; i < Data.Size; i++)
    1644       Data[i].val_i = v;
     1956    for (int i = 0; i < Data.Size; i++)
     1957        Data[i].val_i = v;
    16451958}
    16461959
    16471960//-----------------------------------------------------------------------------
    1648 // ImGuiTextFilter
     1961// [SECTION] ImGuiTextFilter
    16491962//-----------------------------------------------------------------------------
    16501963
     
    16521965ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
    16531966{
    1654    if (default_filter)
    1655    {
    1656       ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
    1657       Build();
    1658    }
    1659    else
    1660    {
    1661       InputBuf[0] = 0;
    1662       CountGrep = 0;
    1663    }
     1967    if (default_filter)
     1968    {
     1969        ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
     1970        Build();
     1971    }
     1972    else
     1973    {
     1974        InputBuf[0] = 0;
     1975        CountGrep = 0;
     1976    }
    16641977}
    16651978
    16661979bool ImGuiTextFilter::Draw(const char* label, float width)
    16671980{
    1668    if (width != 0.0f)
    1669       ImGui::PushItemWidth(width);
    1670    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
    1671    if (width != 0.0f)
    1672       ImGui::PopItemWidth();
    1673    if (value_changed)
    1674       Build();
    1675    return value_changed;
    1676 }
    1677 
    1678 void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>& out)
    1679 {
    1680    out.resize(0);
    1681    const char* wb = b;
    1682    const char* we = wb;
    1683    while (we < e)
    1684    {
    1685       if (*we == separator)
    1686       {
    1687          out.push_back(TextRange(wb, we));
    1688          wb = we + 1;
    1689       }
    1690       we++;
    1691    }
    1692    if (wb != we)
    1693       out.push_back(TextRange(wb, we));
     1981    if (width != 0.0f)
     1982        ImGui::SetNextItemWidth(width);
     1983    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
     1984    if (value_changed)
     1985        Build();
     1986    return value_changed;
     1987}
     1988
     1989void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRange>* out) const
     1990{
     1991    out->resize(0);
     1992    const char* wb = b;
     1993    const char* we = wb;
     1994    while (we < e)
     1995    {
     1996        if (*we == separator)
     1997        {
     1998            out->push_back(ImGuiTextRange(wb, we));
     1999            wb = we + 1;
     2000        }
     2001        we++;
     2002    }
     2003    if (wb != we)
     2004        out->push_back(ImGuiTextRange(wb, we));
    16942005}
    16952006
    16962007void ImGuiTextFilter::Build()
    16972008{
    1698    Filters.resize(0);
    1699    TextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
    1700    input_range.split(',', Filters);
    1701 
    1702    CountGrep = 0;
    1703    for (int i = 0; i != Filters.Size; i++)
    1704    {
    1705       Filters[i].trim_blanks();
    1706       if (Filters[i].empty())
    1707          continue;
    1708       if (Filters[i].front() != '-')
    1709          CountGrep += 1;
    1710    }
     2009    Filters.resize(0);
     2010    ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
     2011    input_range.split(',', &Filters);
     2012
     2013    CountGrep = 0;
     2014    for (int i = 0; i != Filters.Size; i++)
     2015    {
     2016        ImGuiTextRange& f = Filters[i];
     2017        while (f.b < f.e && ImCharIsBlankA(f.b[0]))
     2018            f.b++;
     2019        while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
     2020            f.e--;
     2021        if (f.empty())
     2022            continue;
     2023        if (Filters[i].b[0] != '-')
     2024            CountGrep += 1;
     2025    }
    17112026}
    17122027
    17132028bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
    17142029{
    1715    if (Filters.empty())
    1716       return true;
    1717 
    1718    if (text == NULL)
    1719       text = "";
    1720 
    1721    for (int i = 0; i != Filters.Size; i++)
    1722    {
    1723       const TextRange& f = Filters[i];
    1724       if (f.empty())
    1725          continue;
    1726       if (f.front() == '-')
    1727       {
    1728          // Subtract
    1729          if (ImStristr(text, text_end, f.begin() + 1, f.end()) != NULL)
    1730             return false;
    1731       }
    1732       else
    1733       {
    1734          // Grep
    1735          if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
    1736             return true;
    1737       }
    1738    }
    1739 
    1740    // Implicit * grep
    1741    if (CountGrep == 0)
    1742       return true;
    1743 
    1744    return false;
     2030    if (Filters.empty())
     2031        return true;
     2032
     2033    if (text == NULL)
     2034        text = "";
     2035
     2036    for (int i = 0; i != Filters.Size; i++)
     2037    {
     2038        const ImGuiTextRange& f = Filters[i];
     2039        if (f.empty())
     2040            continue;
     2041        if (f.b[0] == '-')
     2042        {
     2043            // Subtract
     2044            if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
     2045                return false;
     2046        }
     2047        else
     2048        {
     2049            // Grep
     2050            if (ImStristr(text, text_end, f.b, f.e) != NULL)
     2051                return true;
     2052        }
     2053    }
     2054
     2055    // Implicit * grep
     2056    if (CountGrep == 0)
     2057        return true;
     2058
     2059    return false;
    17452060}
    17462061
    17472062//-----------------------------------------------------------------------------
    1748 // ImGuiTextBuffer
     2063// [SECTION] ImGuiTextBuffer
    17492064//-----------------------------------------------------------------------------
    17502065
     
    17522067// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
    17532068#ifndef va_copy
     2069#if defined(__GNUC__) || defined(__clang__)
     2070#define va_copy(dest, src) __builtin_va_copy(dest, src)
     2071#else
    17542072#define va_copy(dest, src) (dest = src)
    17552073#endif
     2074#endif
     2075
     2076char ImGuiTextBuffer::EmptyString[1] = { 0 };
     2077
     2078void ImGuiTextBuffer::append(const char* str, const char* str_end)
     2079{
     2080    int len = str_end ? (int)(str_end - str) : (int)strlen(str);
     2081
     2082    // Add zero-terminator the first time
     2083    const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
     2084    const int needed_sz = write_off + len;
     2085    if (write_off + len >= Buf.Capacity)
     2086    {
     2087        int new_capacity = Buf.Capacity * 2;
     2088        Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
     2089    }
     2090
     2091    Buf.resize(needed_sz);
     2092    memcpy(&Buf[write_off - 1], str, (size_t)len);
     2093    Buf[write_off - 1 + len] = 0;
     2094}
     2095
     2096void ImGuiTextBuffer::appendf(const char* fmt, ...)
     2097{
     2098    va_list args;
     2099    va_start(args, fmt);
     2100    appendfv(fmt, args);
     2101    va_end(args);
     2102}
    17562103
    17572104// Helper: Text buffer for logging/accumulating text
    17582105void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
    17592106{
    1760    va_list args_copy;
    1761    va_copy(args_copy, args);
    1762 
    1763    int len = ImFormatStringV(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
    1764    if (len <= 0)
    1765    {
    1766       va_end(args_copy);
    1767       return;
    1768    }
    1769 
    1770    const int write_off = Buf.Size;
    1771    const int needed_sz = write_off + len;
    1772    if (write_off + len >= Buf.Capacity)
    1773    {
    1774       int double_capacity = Buf.Capacity * 2;
    1775       Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);
    1776    }
    1777 
    1778    Buf.resize(needed_sz);
    1779    ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
    1780    va_end(args_copy);
    1781 }
    1782 
    1783 void ImGuiTextBuffer::appendf(const char* fmt, ...)
    1784 {
    1785    va_list args;
    1786    va_start(args, fmt);
    1787    appendfv(fmt, args);
    1788    va_end(args);
     2107    va_list args_copy;
     2108    va_copy(args_copy, args);
     2109
     2110    int len = ImFormatStringV(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
     2111    if (len <= 0)
     2112    {
     2113        va_end(args_copy);
     2114        return;
     2115    }
     2116
     2117    // Add zero-terminator the first time
     2118    const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
     2119    const int needed_sz = write_off + len;
     2120    if (write_off + len >= Buf.Capacity)
     2121    {
     2122        int new_capacity = Buf.Capacity * 2;
     2123        Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
     2124    }
     2125
     2126    Buf.resize(needed_sz);
     2127    ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
     2128    va_end(args_copy);
    17892129}
    17902130
    17912131//-----------------------------------------------------------------------------
    1792 // ImGuiSimpleColumns (internal use only)
     2132// [SECTION] ImGuiListClipper
     2133// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed
     2134// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO)
    17932135//-----------------------------------------------------------------------------
    17942136
    1795 ImGuiMenuColumns::ImGuiMenuColumns()
    1796 {
    1797    Count = 0;
    1798    Spacing = Width = NextWidth = 0.0f;
    1799    memset(Pos, 0, sizeof(Pos));
    1800    memset(NextWidths, 0, sizeof(NextWidths));
    1801 }
    1802 
    1803 void ImGuiMenuColumns::Update(int count, float spacing, bool clear)
    1804 {
    1805    IM_ASSERT(Count <= IM_ARRAYSIZE(Pos));
    1806    Count = count;
    1807    Width = NextWidth = 0.0f;
    1808    Spacing = spacing;
    1809    if (clear) memset(NextWidths, 0, sizeof(NextWidths));
    1810    for (int i = 0; i < Count; i++)
    1811    {
    1812       if (i > 0 && NextWidths[i] > 0.0f)
    1813          Width += Spacing;
    1814       Pos[i] = (float)(int)Width;
    1815       Width += NextWidths[i];
    1816       NextWidths[i] = 0.0f;
    1817    }
    1818 }
    1819 
    1820 float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double
    1821 {
    1822    NextWidth = 0.0f;
    1823    NextWidths[0] = ImMax(NextWidths[0], w0);
    1824    NextWidths[1] = ImMax(NextWidths[1], w1);
    1825    NextWidths[2] = ImMax(NextWidths[2], w2);
    1826    for (int i = 0; i < 3; i++)
    1827       NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);
    1828    return ImMax(Width, NextWidth);
    1829 }
    1830 
    1831 float ImGuiMenuColumns::CalcExtraSpace(float avail_w)
    1832 {
    1833    return ImMax(0.0f, avail_w - Width);
    1834 }
    1835 
    1836 //-----------------------------------------------------------------------------
    1837 // ImGuiListClipper
    1838 //-----------------------------------------------------------------------------
    1839 
    1840 static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
    1841 {
    1842    // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor.
    1843    // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
    1844    // The clipper should probably have a 4th step to display the last item in a regular manner.
    1845    ImGui::SetCursorPosY(pos_y);
    1846    ImGuiWindow* window = ImGui::GetCurrentWindow();
    1847    window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;      // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage.
    1848    window->DC.PrevLineHeight = (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.
    1849    if (window->DC.ColumnsSet)
    1850       window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;           // Setting this so that cell Y position are set properly
    1851 }
    1852 
    1853 // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
     2137// Helper to calculate coarse clipping of large list of evenly sized items.
     2138// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
     2139// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
     2140void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
     2141{
     2142    ImGuiContext& g = *GImGui;
     2143    ImGuiWindow* window = g.CurrentWindow;
     2144    if (g.LogEnabled)
     2145    {
     2146        // If logging is active, do not perform any clipping
     2147        *out_items_display_start = 0;
     2148        *out_items_display_end = items_count;
     2149        return;
     2150    }
     2151    if (window->SkipItems)
     2152    {
     2153        *out_items_display_start = *out_items_display_end = 0;
     2154        return;
     2155    }
     2156
     2157    // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect
     2158    ImRect unclipped_rect = window->ClipRect;
     2159    if (g.NavMoveRequest)
     2160        unclipped_rect.Add(g.NavScoringRect);
     2161    if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId)
     2162        unclipped_rect.Add(ImRect(window->Pos + window->NavRectRel[0].Min, window->Pos + window->NavRectRel[0].Max));
     2163
     2164    const ImVec2 pos = window->DC.CursorPos;
     2165    int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
     2166    int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
     2167
     2168    // When performing a navigation request, ensure we have one item extra in the direction we are moving to
     2169    if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up)
     2170        start--;
     2171    if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down)
     2172        end++;
     2173
     2174    start = ImClamp(start, 0, items_count);
     2175    end = ImClamp(end + 1, start, items_count);
     2176    *out_items_display_start = start;
     2177    *out_items_display_end = end;
     2178}
     2179
     2180static void SetCursorPosYAndSetupForPrevLine(float pos_y, float line_height)
     2181{
     2182    // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
     2183    // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
     2184    // The clipper should probably have a 4th step to display the last item in a regular manner.
     2185    ImGuiContext& g = *GImGui;
     2186    ImGuiWindow* window = g.CurrentWindow;
     2187    window->DC.CursorPos.y = pos_y;
     2188    window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y);
     2189    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.
     2190    window->DC.PrevLineSize.y = (line_height - g.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.
     2191    if (ImGuiColumns* columns = window->DC.CurrentColumns)
     2192        columns->LineMinY = window->DC.CursorPos.y;                         // Setting this so that cell Y position are set properly
     2193}
     2194
     2195ImGuiListClipper::ImGuiListClipper()
     2196{
     2197    memset(this, 0, sizeof(*this));
     2198    ItemsCount = -1;
     2199}
     2200
     2201ImGuiListClipper::~ImGuiListClipper()
     2202{
     2203    IM_ASSERT(ItemsCount == -1 && "Forgot to call End(), or to Step() until false?");
     2204}
     2205
     2206// Use case A: Begin() called from constructor with items_height<0, then called again from Step() in StepNo 1
    18542207// Use case B: Begin() called from constructor with items_height>0
    18552208// 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.
    1856 void ImGuiListClipper::Begin(int count, float items_height)
    1857 {
    1858    StartPosY = ImGui::GetCursorPosY();
    1859    ItemsHeight = items_height;
    1860    ItemsCount = count;
    1861    StepNo = 0;
    1862    DisplayEnd = DisplayStart = -1;
    1863    if (ItemsHeight > 0.0f)
    1864    {
    1865       ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display
    1866       if (DisplayStart > 0)
    1867          SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor
    1868       StepNo = 2;
    1869    }
     2209void ImGuiListClipper::Begin(int items_count, float items_height)
     2210{
     2211    ImGuiContext& g = *GImGui;
     2212    ImGuiWindow* window = g.CurrentWindow;
     2213
     2214    StartPosY = window->DC.CursorPos.y;
     2215    ItemsHeight = items_height;
     2216    ItemsCount = items_count;
     2217    StepNo = 0;
     2218    DisplayStart = -1;
     2219    DisplayEnd = 0;
    18702220}
    18712221
    18722222void ImGuiListClipper::End()
    18732223{
    1874    if (ItemsCount < 0)
    1875       return;
    1876    // 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.
    1877    if (ItemsCount < INT_MAX)
    1878       SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
    1879    ItemsCount = -1;
    1880    StepNo = 3;
     2224    if (ItemsCount < 0) // Already ended
     2225        return;
     2226
     2227    // 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.
     2228    if (ItemsCount < INT_MAX && DisplayStart >= 0)
     2229        SetCursorPosYAndSetupForPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight);
     2230    ItemsCount = -1;
     2231    StepNo = 3;
    18812232}
    18822233
    18832234bool ImGuiListClipper::Step()
    18842235{
    1885    if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
    1886    {
    1887       ItemsCount = -1;
    1888       return false;
    1889    }
    1890    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.
    1891    {
    1892       DisplayStart = 0;
    1893       DisplayEnd = 1;
    1894       StartPosY = ImGui::GetCursorPosY();
    1895       StepNo = 1;
    1896       return true;
    1897    }
    1898    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.
    1899    {
    1900       if (ItemsCount == 1) { ItemsCount = -1; return false; }
    1901       float items_height = ImGui::GetCursorPosY() - StartPosY;
    1902       IM_ASSERT(items_height > 0.0f);   // If this triggers, it means Item 0 hasn't moved the cursor vertically
    1903       Begin(ItemsCount - 1, items_height);
    1904       DisplayStart++;
    1905       DisplayEnd++;
    1906       StepNo = 3;
    1907       return true;
    1908    }
    1909    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.
    1910    {
    1911       IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);
    1912       StepNo = 3;
    1913       return true;
    1914    }
    1915    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.
    1916       End();
    1917    return false;
     2236    ImGuiContext& g = *GImGui;
     2237    ImGuiWindow* window = g.CurrentWindow;
     2238
     2239    // Reached end of list
     2240    if (DisplayEnd >= ItemsCount || window->SkipItems)
     2241    {
     2242        End();
     2243        return false;
     2244    }
     2245
     2246    // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height)
     2247    if (StepNo == 0)
     2248    {
     2249        StartPosY = window->DC.CursorPos.y;
     2250        if (ItemsHeight <= 0.0f)
     2251        {
     2252            // Submit the first item so we can measure its height (generally it is 0..1)
     2253            DisplayStart = 0;
     2254            DisplayEnd = 1;
     2255            StepNo = 1;
     2256            return true;
     2257        }
     2258
     2259        // Already has item height (given by user in Begin): skip to calculating step
     2260        DisplayStart = DisplayEnd;
     2261        StepNo = 2;
     2262    }
     2263
     2264    // Step 1: the clipper infer height from first element
     2265    if (StepNo == 1)
     2266    {
     2267        IM_ASSERT(ItemsHeight <= 0.0f);
     2268        ItemsHeight = window->DC.CursorPos.y - StartPosY;
     2269        IM_ASSERT(ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
     2270        StepNo = 2;
     2271    }
     2272
     2273    // Step 2: calculate the actual range of elements to display, and position the cursor before the first element
     2274    if (StepNo == 2)
     2275    {
     2276        IM_ASSERT(ItemsHeight > 0.0f);
     2277
     2278        int already_submitted = DisplayEnd;
     2279        ImGui::CalcListClipping(ItemsCount - already_submitted, ItemsHeight, &DisplayStart, &DisplayEnd);
     2280        DisplayStart += already_submitted;
     2281        DisplayEnd += already_submitted;
     2282
     2283        // Seek cursor
     2284        if (DisplayStart > already_submitted)
     2285            SetCursorPosYAndSetupForPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight);
     2286
     2287        StepNo = 3;
     2288        return true;
     2289    }
     2290
     2291    // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd),
     2292    // Advance the cursor to the end of the list and then returns 'false' to end the loop.
     2293    if (StepNo == 3)
     2294    {
     2295        // Seek cursor
     2296        if (ItemsCount < INT_MAX)
     2297            SetCursorPosYAndSetupForPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
     2298        ItemsCount = -1;
     2299        return false;
     2300    }
     2301
     2302    IM_ASSERT(0);
     2303    return false;
    19182304}
    19192305
    19202306//-----------------------------------------------------------------------------
    1921 // ImGuiWindow
     2307// [SECTION] STYLING
    19222308//-----------------------------------------------------------------------------
    19232309
     2310ImGuiStyle& ImGui::GetStyle()
     2311{
     2312    IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
     2313    return GImGui->Style;
     2314}
     2315
     2316ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
     2317{
     2318    ImGuiStyle& style = GImGui->Style;
     2319    ImVec4 c = style.Colors[idx];
     2320    c.w *= style.Alpha * alpha_mul;
     2321    return ColorConvertFloat4ToU32(c);
     2322}
     2323
     2324ImU32 ImGui::GetColorU32(const ImVec4& col)
     2325{
     2326    ImGuiStyle& style = GImGui->Style;
     2327    ImVec4 c = col;
     2328    c.w *= style.Alpha;
     2329    return ColorConvertFloat4ToU32(c);
     2330}
     2331
     2332const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
     2333{
     2334    ImGuiStyle& style = GImGui->Style;
     2335    return style.Colors[idx];
     2336}
     2337
     2338ImU32 ImGui::GetColorU32(ImU32 col)
     2339{
     2340    ImGuiStyle& style = GImGui->Style;
     2341    if (style.Alpha >= 1.0f)
     2342        return col;
     2343    ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
     2344    a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
     2345    return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
     2346}
     2347
     2348// 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
     2349void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
     2350{
     2351    ImGuiContext& g = *GImGui;
     2352    ImGuiColorMod backup;
     2353    backup.Col = idx;
     2354    backup.BackupValue = g.Style.Colors[idx];
     2355    g.ColorModifiers.push_back(backup);
     2356    g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
     2357}
     2358
     2359void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
     2360{
     2361    ImGuiContext& g = *GImGui;
     2362    ImGuiColorMod backup;
     2363    backup.Col = idx;
     2364    backup.BackupValue = g.Style.Colors[idx];
     2365    g.ColorModifiers.push_back(backup);
     2366    g.Style.Colors[idx] = col;
     2367}
     2368
     2369void ImGui::PopStyleColor(int count)
     2370{
     2371    ImGuiContext& g = *GImGui;
     2372    while (count > 0)
     2373    {
     2374        ImGuiColorMod& backup = g.ColorModifiers.back();
     2375        g.Style.Colors[backup.Col] = backup.BackupValue;
     2376        g.ColorModifiers.pop_back();
     2377        count--;
     2378    }
     2379}
     2380
     2381struct ImGuiStyleVarInfo
     2382{
     2383    ImGuiDataType   Type;
     2384    ImU32           Count;
     2385    ImU32           Offset;
     2386    void*           GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
     2387};
     2388
     2389static const ImGuiStyleVarInfo GStyleVarInfo[] =
     2390{
     2391    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) },               // ImGuiStyleVar_Alpha
     2392    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) },       // ImGuiStyleVar_WindowPadding
     2393    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) },      // ImGuiStyleVar_WindowRounding
     2394    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) },    // ImGuiStyleVar_WindowBorderSize
     2395    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) },       // ImGuiStyleVar_WindowMinSize
     2396    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) },    // ImGuiStyleVar_WindowTitleAlign
     2397    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) },       // ImGuiStyleVar_ChildRounding
     2398    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) },     // ImGuiStyleVar_ChildBorderSize
     2399    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) },       // ImGuiStyleVar_PopupRounding
     2400    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) },     // ImGuiStyleVar_PopupBorderSize
     2401    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) },        // ImGuiStyleVar_FramePadding
     2402    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) },       // ImGuiStyleVar_FrameRounding
     2403    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) },     // ImGuiStyleVar_FrameBorderSize
     2404    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) },         // ImGuiStyleVar_ItemSpacing
     2405    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) },    // ImGuiStyleVar_ItemInnerSpacing
     2406    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) },       // ImGuiStyleVar_IndentSpacing
     2407    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) },       // ImGuiStyleVar_ScrollbarSize
     2408    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) },   // ImGuiStyleVar_ScrollbarRounding
     2409    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) },         // ImGuiStyleVar_GrabMinSize
     2410    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) },        // ImGuiStyleVar_GrabRounding
     2411    { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) },         // ImGuiStyleVar_TabRounding
     2412    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) },     // ImGuiStyleVar_ButtonTextAlign
     2413    { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
     2414};
     2415
     2416static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
     2417{
     2418    IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
     2419    IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
     2420    return &GStyleVarInfo[idx];
     2421}
     2422
     2423void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
     2424{
     2425    const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
     2426    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
     2427    {
     2428        ImGuiContext& g = *GImGui;
     2429        float* pvar = (float*)var_info->GetVarPtr(&g.Style);
     2430        g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
     2431        *pvar = val;
     2432        return;
     2433    }
     2434    IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!");
     2435}
     2436
     2437void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
     2438{
     2439    const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
     2440    if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
     2441    {
     2442        ImGuiContext& g = *GImGui;
     2443        ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
     2444        g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
     2445        *pvar = val;
     2446        return;
     2447    }
     2448    IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!");
     2449}
     2450
     2451void ImGui::PopStyleVar(int count)
     2452{
     2453    ImGuiContext& g = *GImGui;
     2454    while (count > 0)
     2455    {
     2456        // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
     2457        ImGuiStyleMod& backup = g.StyleModifiers.back();
     2458        const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
     2459        void* data = info->GetVarPtr(&g.Style);
     2460        if (info->Type == ImGuiDataType_Float && info->Count == 1)      { ((float*)data)[0] = backup.BackupFloat[0]; }
     2461        else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
     2462        g.StyleModifiers.pop_back();
     2463        count--;
     2464    }
     2465}
     2466
     2467const char* ImGui::GetStyleColorName(ImGuiCol idx)
     2468{
     2469    // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
     2470    switch (idx)
     2471    {
     2472    case ImGuiCol_Text: return "Text";
     2473    case ImGuiCol_TextDisabled: return "TextDisabled";
     2474    case ImGuiCol_WindowBg: return "WindowBg";
     2475    case ImGuiCol_ChildBg: return "ChildBg";
     2476    case ImGuiCol_PopupBg: return "PopupBg";
     2477    case ImGuiCol_Border: return "Border";
     2478    case ImGuiCol_BorderShadow: return "BorderShadow";
     2479    case ImGuiCol_FrameBg: return "FrameBg";
     2480    case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
     2481    case ImGuiCol_FrameBgActive: return "FrameBgActive";
     2482    case ImGuiCol_TitleBg: return "TitleBg";
     2483    case ImGuiCol_TitleBgActive: return "TitleBgActive";
     2484    case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
     2485    case ImGuiCol_MenuBarBg: return "MenuBarBg";
     2486    case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
     2487    case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
     2488    case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
     2489    case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
     2490    case ImGuiCol_CheckMark: return "CheckMark";
     2491    case ImGuiCol_SliderGrab: return "SliderGrab";
     2492    case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
     2493    case ImGuiCol_Button: return "Button";
     2494    case ImGuiCol_ButtonHovered: return "ButtonHovered";
     2495    case ImGuiCol_ButtonActive: return "ButtonActive";
     2496    case ImGuiCol_Header: return "Header";
     2497    case ImGuiCol_HeaderHovered: return "HeaderHovered";
     2498    case ImGuiCol_HeaderActive: return "HeaderActive";
     2499    case ImGuiCol_Separator: return "Separator";
     2500    case ImGuiCol_SeparatorHovered: return "SeparatorHovered";
     2501    case ImGuiCol_SeparatorActive: return "SeparatorActive";
     2502    case ImGuiCol_ResizeGrip: return "ResizeGrip";
     2503    case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
     2504    case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
     2505    case ImGuiCol_Tab: return "Tab";
     2506    case ImGuiCol_TabHovered: return "TabHovered";
     2507    case ImGuiCol_TabActive: return "TabActive";
     2508    case ImGuiCol_TabUnfocused: return "TabUnfocused";
     2509    case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
     2510    case ImGuiCol_PlotLines: return "PlotLines";
     2511    case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
     2512    case ImGuiCol_PlotHistogram: return "PlotHistogram";
     2513    case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
     2514    case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
     2515    case ImGuiCol_DragDropTarget: return "DragDropTarget";
     2516    case ImGuiCol_NavHighlight: return "NavHighlight";
     2517    case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
     2518    case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
     2519    case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
     2520    }
     2521    IM_ASSERT(0);
     2522    return "Unknown";
     2523}
     2524
     2525
     2526//-----------------------------------------------------------------------------
     2527// [SECTION] RENDER HELPERS
     2528// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change,
     2529// we need a nicer separation between low-level functions and high-level functions relying on the ImGui context.
     2530// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context.
     2531//-----------------------------------------------------------------------------
     2532
     2533const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
     2534{
     2535    const char* text_display_end = text;
     2536    if (!text_end)
     2537        text_end = (const char*)-1;
     2538
     2539    while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
     2540        text_display_end++;
     2541    return text_display_end;
     2542}
     2543
     2544// Internal ImGui functions to render text
     2545// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
     2546void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
     2547{
     2548    ImGuiContext& g = *GImGui;
     2549    ImGuiWindow* window = g.CurrentWindow;
     2550
     2551    // Hide anything after a '##' string
     2552    const char* text_display_end;
     2553    if (hide_text_after_hash)
     2554    {
     2555        text_display_end = FindRenderedTextEnd(text, text_end);
     2556    }
     2557    else
     2558    {
     2559        if (!text_end)
     2560            text_end = text + strlen(text); // FIXME-OPT
     2561        text_display_end = text_end;
     2562    }
     2563
     2564    if (text != text_display_end)
     2565    {
     2566        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
     2567        if (g.LogEnabled)
     2568            LogRenderedText(&pos, text, text_display_end);
     2569    }
     2570}
     2571
     2572void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
     2573{
     2574    ImGuiContext& g = *GImGui;
     2575    ImGuiWindow* window = g.CurrentWindow;
     2576
     2577    if (!text_end)
     2578        text_end = text + strlen(text); // FIXME-OPT
     2579
     2580    if (text != text_end)
     2581    {
     2582        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
     2583        if (g.LogEnabled)
     2584            LogRenderedText(&pos, text, text_end);
     2585    }
     2586}
     2587
     2588// Default clip_rect uses (pos_min,pos_max)
     2589// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
     2590void 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)
     2591{
     2592    // Perform CPU side clipping for single clipped element to avoid using scissor state
     2593    ImVec2 pos = pos_min;
     2594    const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
     2595
     2596    const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
     2597    const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
     2598    bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
     2599    if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
     2600        need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
     2601
     2602    // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
     2603    if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
     2604    if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
     2605
     2606    // Render
     2607    if (need_clipping)
     2608    {
     2609        ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
     2610        draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
     2611    }
     2612    else
     2613    {
     2614        draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
     2615    }
     2616}
     2617
     2618void 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)
     2619{
     2620    // Hide anything after a '##' string
     2621    const char* text_display_end = FindRenderedTextEnd(text, text_end);
     2622    const int text_len = (int)(text_display_end - text);
     2623    if (text_len == 0)
     2624        return;
     2625
     2626    ImGuiContext& g = *GImGui;
     2627    ImGuiWindow* window = g.CurrentWindow;
     2628    RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
     2629    if (g.LogEnabled)
     2630        LogRenderedText(&pos_min, text, text_display_end);
     2631}
     2632
     2633
     2634// Another overly complex function until we reorganize everything into a nice all-in-one helper.
     2635// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
     2636// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
     2637void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
     2638{
     2639    ImGuiContext& g = *GImGui;
     2640    if (text_end_full == NULL)
     2641        text_end_full = FindRenderedTextEnd(text);
     2642    const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
     2643
     2644    //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
     2645    //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255));
     2646    //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255));
     2647    // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
     2648    if (text_size.x > pos_max.x - pos_min.x)
     2649    {
     2650        // Hello wo...
     2651        // |       |   |
     2652        // min   max   ellipsis_max
     2653        //          <-> this is generally some padding value
     2654
     2655        const ImFont* font = draw_list->_Data->Font;
     2656        const float font_size = draw_list->_Data->FontSize;
     2657        const char* text_end_ellipsis = NULL;
     2658
     2659        ImWchar ellipsis_char = font->EllipsisChar;
     2660        int ellipsis_char_count = 1;
     2661        if (ellipsis_char == (ImWchar)-1)
     2662        {
     2663            ellipsis_char = (ImWchar)'.';
     2664            ellipsis_char_count = 3;
     2665        }
     2666        const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
     2667
     2668        float ellipsis_glyph_width = glyph->X1;                 // Width of the glyph with no padding on either side
     2669        float ellipsis_total_width = ellipsis_glyph_width;      // Full width of entire ellipsis
     2670
     2671        if (ellipsis_char_count > 1)
     2672        {
     2673            // Full ellipsis size without free spacing after it.
     2674            const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize);
     2675            ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
     2676            ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
     2677        }
     2678
     2679        // We can now claim the space between pos_max.x and ellipsis_max.x
     2680        const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
     2681        float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
     2682        if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
     2683        {
     2684            // Always display at least 1 character if there's no room for character + ellipsis
     2685            text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full);
     2686            text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
     2687        }
     2688        while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
     2689        {
     2690            // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
     2691            text_end_ellipsis--;
     2692            text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
     2693        }
     2694
     2695        // Render text, render ellipsis
     2696        RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
     2697        float ellipsis_x = pos_min.x + text_size_clipped_x;
     2698        if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
     2699            for (int i = 0; i < ellipsis_char_count; i++)
     2700            {
     2701                font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
     2702                ellipsis_x += ellipsis_glyph_width;
     2703            }
     2704    }
     2705    else
     2706    {
     2707        RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f));
     2708    }
     2709
     2710    if (g.LogEnabled)
     2711        LogRenderedText(&pos_min, text, text_end_full);
     2712}
     2713
     2714// Render a rectangle shaped with optional rounding and borders
     2715void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
     2716{
     2717    ImGuiContext& g = *GImGui;
     2718    ImGuiWindow* window = g.CurrentWindow;
     2719    window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
     2720    const float border_size = g.Style.FrameBorderSize;
     2721    if (border && border_size > 0.0f)
     2722    {
     2723        window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
     2724        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
     2725    }
     2726}
     2727
     2728void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
     2729{
     2730    ImGuiContext& g = *GImGui;
     2731    ImGuiWindow* window = g.CurrentWindow;
     2732    const float border_size = g.Style.FrameBorderSize;
     2733    if (border_size > 0.0f)
     2734    {
     2735        window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
     2736        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
     2737    }
     2738}
     2739
     2740void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
     2741{
     2742    ImGuiContext& g = *GImGui;
     2743    if (id != g.NavId)
     2744        return;
     2745    if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
     2746        return;
     2747    ImGuiWindow* window = g.CurrentWindow;
     2748    if (window->DC.NavHideHighlightOneFrame)
     2749        return;
     2750
     2751    float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
     2752    ImRect display_rect = bb;
     2753    display_rect.ClipWith(window->ClipRect);
     2754    if (flags & ImGuiNavHighlightFlags_TypeDefault)
     2755    {
     2756        const float THICKNESS = 2.0f;
     2757        const float DISTANCE = 3.0f + THICKNESS * 0.5f;
     2758        display_rect.Expand(ImVec2(DISTANCE, DISTANCE));
     2759        bool fully_visible = window->ClipRect.Contains(display_rect);
     2760        if (!fully_visible)
     2761            window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
     2762        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);
     2763        if (!fully_visible)
     2764            window->DrawList->PopClipRect();
     2765    }
     2766    if (flags & ImGuiNavHighlightFlags_TypeThin)
     2767    {
     2768        window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
     2769    }
     2770}
     2771
     2772//-----------------------------------------------------------------------------
     2773// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
     2774//-----------------------------------------------------------------------------
     2775
     2776// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
    19242777ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
    1925    : DrawListInst(&context->DrawListSharedData)
    1926 {
    1927    Name = ImStrdup(name);
    1928    ID = ImHash(name, 0);
    1929    IDStack.push_back(ID);
    1930    Flags = 0;
    1931    Pos = ImVec2(0.0f, 0.0f);
    1932    Size = SizeFull = ImVec2(0.0f, 0.0f);
    1933    SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
    1934    WindowPadding = ImVec2(0.0f, 0.0f);
    1935    WindowRounding = 0.0f;
    1936    WindowBorderSize = 0.0f;
    1937    MoveId = GetID("#MOVE");
    1938    ChildId = 0;
    1939    Scroll = ImVec2(0.0f, 0.0f);
    1940    ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
    1941    ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
    1942    ScrollbarSizes = ImVec2(0.0f, 0.0f);
    1943    ScrollbarX = ScrollbarY = false;
    1944    Active = WasActive = false;
    1945    WriteAccessed = false;
    1946    Collapsed = false;
    1947    CollapseToggleWanted = false;
    1948    SkipItems = false;
    1949    Appearing = false;
    1950    CloseButton = false;
    1951    BeginOrderWithinParent = -1;
    1952    BeginOrderWithinContext = -1;
    1953    BeginCount = 0;
    1954    PopupId = 0;
    1955    AutoFitFramesX = AutoFitFramesY = -1;
    1956    AutoFitOnlyGrows = false;
    1957    AutoFitChildAxises = 0x00;
    1958    AutoPosLastDirection = ImGuiDir_None;
    1959    HiddenFrames = 0;
    1960    SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
    1961    SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
    1962 
    1963    LastFrameActive = -1;
    1964    ItemWidthDefault = 0.0f;
    1965    FontWindowScale = 1.0f;
    1966 
    1967    DrawList = &DrawListInst;
    1968    DrawList->_OwnerName = Name;
    1969    ParentWindow = NULL;
    1970    RootWindow = NULL;
    1971    RootWindowForTitleBarHighlight = NULL;
    1972    RootWindowForTabbing = NULL;
    1973    RootWindowForNav = NULL;
    1974 
    1975    NavLastIds[0] = NavLastIds[1] = 0;
    1976    NavRectRel[0] = NavRectRel[1] = ImRect();
    1977    NavLastChildNavWindow = NULL;
    1978 
    1979    FocusIdxAllCounter = FocusIdxTabCounter = -1;
    1980    FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
    1981    FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
     2778    : DrawListInst(&context->DrawListSharedData)
     2779{
     2780    Name = ImStrdup(name);
     2781    ID = ImHashStr(name);
     2782    IDStack.push_back(ID);
     2783    Flags = ImGuiWindowFlags_None;
     2784    Pos = ImVec2(0.0f, 0.0f);
     2785    Size = SizeFull = ImVec2(0.0f, 0.0f);
     2786    ContentSize = ContentSizeExplicit = ImVec2(0.0f, 0.0f);
     2787    WindowPadding = ImVec2(0.0f, 0.0f);
     2788    WindowRounding = 0.0f;
     2789    WindowBorderSize = 0.0f;
     2790    NameBufLen = (int)strlen(name) + 1;
     2791    MoveId = GetID("#MOVE");
     2792    ChildId = 0;
     2793    Scroll = ImVec2(0.0f, 0.0f);
     2794    ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
     2795    ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
     2796    ScrollbarSizes = ImVec2(0.0f, 0.0f);
     2797    ScrollbarX = ScrollbarY = false;
     2798    Active = WasActive = false;
     2799    WriteAccessed = false;
     2800    Collapsed = false;
     2801    WantCollapseToggle = false;
     2802    SkipItems = false;
     2803    Appearing = false;
     2804    Hidden = false;
     2805    IsFallbackWindow = false;
     2806    HasCloseButton = false;
     2807    ResizeBorderHeld = -1;
     2808    BeginCount = 0;
     2809    BeginOrderWithinParent = -1;
     2810    BeginOrderWithinContext = -1;
     2811    PopupId = 0;
     2812    AutoFitFramesX = AutoFitFramesY = -1;
     2813    AutoFitChildAxises = 0x00;
     2814    AutoFitOnlyGrows = false;
     2815    AutoPosLastDirection = ImGuiDir_None;
     2816    HiddenFramesCanSkipItems = HiddenFramesCannotSkipItems = 0;
     2817    SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
     2818    SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
     2819
     2820    InnerRect = ImRect(0.0f, 0.0f, 0.0f, 0.0f); // Clear so the InnerRect.GetSize() code in Begin() doesn't lead to overflow even if the result isn't used.
     2821
     2822    LastFrameActive = -1;
     2823    LastTimeActive = -1.0f;
     2824    ItemWidthDefault = 0.0f;
     2825    FontWindowScale = 1.0f;
     2826    SettingsOffset = -1;
     2827
     2828    DrawList = &DrawListInst;
     2829    DrawList->_OwnerName = Name;
     2830    ParentWindow = NULL;
     2831    RootWindow = NULL;
     2832    RootWindowForTitleBarHighlight = NULL;
     2833    RootWindowForNav = NULL;
     2834
     2835    NavLastIds[0] = NavLastIds[1] = 0;
     2836    NavRectRel[0] = NavRectRel[1] = ImRect();
     2837    NavLastChildNavWindow = NULL;
     2838
     2839    MemoryCompacted = false;
     2840    MemoryDrawListIdxCapacity = MemoryDrawListVtxCapacity = 0;
    19822841}
    19832842
    19842843ImGuiWindow::~ImGuiWindow()
    19852844{
    1986    IM_ASSERT(DrawList == &DrawListInst);
    1987    IM_DELETE(Name);
    1988    for (int i = 0; i != ColumnsStorage.Size; i++)
    1989       ColumnsStorage[i].~ImGuiColumnsSet();
     2845    IM_ASSERT(DrawList == &DrawListInst);
     2846    IM_DELETE(Name);
     2847    for (int i = 0; i != ColumnsStorage.Size; i++)
     2848        ColumnsStorage[i].~ImGuiColumns();
    19902849}
    19912850
    19922851ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
    19932852{
    1994    ImGuiID seed = IDStack.back();
    1995    ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
    1996    ImGui::KeepAliveID(id);
    1997    return id;
     2853    ImGuiID seed = IDStack.back();
     2854    ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
     2855    ImGui::KeepAliveID(id);
     2856#ifdef IMGUI_ENABLE_TEST_ENGINE
     2857    ImGuiContext& g = *GImGui;
     2858    IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end);
     2859#endif
     2860    return id;
    19982861}
    19992862
    20002863ImGuiID ImGuiWindow::GetID(const void* ptr)
    20012864{
    2002    ImGuiID seed = IDStack.back();
    2003    ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
    2004    ImGui::KeepAliveID(id);
    2005    return id;
     2865    ImGuiID seed = IDStack.back();
     2866    ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
     2867    ImGui::KeepAliveID(id);
     2868#ifdef IMGUI_ENABLE_TEST_ENGINE
     2869    ImGuiContext& g = *GImGui;
     2870    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr);
     2871#endif
     2872    return id;
     2873}
     2874
     2875ImGuiID ImGuiWindow::GetID(int n)
     2876{
     2877    ImGuiID seed = IDStack.back();
     2878    ImGuiID id = ImHashData(&n, sizeof(n), seed);
     2879    ImGui::KeepAliveID(id);
     2880#ifdef IMGUI_ENABLE_TEST_ENGINE
     2881    ImGuiContext& g = *GImGui;
     2882    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n);
     2883#endif
     2884    return id;
    20062885}
    20072886
    20082887ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
    20092888{
    2010    ImGuiID seed = IDStack.back();
    2011    return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
     2889    ImGuiID seed = IDStack.back();
     2890    ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
     2891#ifdef IMGUI_ENABLE_TEST_ENGINE
     2892    ImGuiContext& g = *GImGui;
     2893    IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end);
     2894#endif
     2895    return id;
     2896}
     2897
     2898ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
     2899{
     2900    ImGuiID seed = IDStack.back();
     2901    ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
     2902#ifdef IMGUI_ENABLE_TEST_ENGINE
     2903    ImGuiContext& g = *GImGui;
     2904    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr);
     2905#endif
     2906    return id;
     2907}
     2908
     2909ImGuiID ImGuiWindow::GetIDNoKeepAlive(int n)
     2910{
     2911    ImGuiID seed = IDStack.back();
     2912    ImGuiID id = ImHashData(&n, sizeof(n), seed);
     2913#ifdef IMGUI_ENABLE_TEST_ENGINE
     2914    ImGuiContext& g = *GImGui;
     2915    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n);
     2916#endif
     2917    return id;
    20122918}
    20132919
     
    20152921ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
    20162922{
    2017    ImGuiID seed = IDStack.back();
    2018    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) };
    2019    ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed);
    2020    ImGui::KeepAliveID(id);
    2021    return id;
    2022 }
    2023 
    2024 //-----------------------------------------------------------------------------
    2025 // Internal API exposed in imgui_internal.h
    2026 //-----------------------------------------------------------------------------
     2923    ImGuiID seed = IDStack.back();
     2924    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) };
     2925    ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed);
     2926    ImGui::KeepAliveID(id);
     2927    return id;
     2928}
    20272929
    20282930static void SetCurrentWindow(ImGuiWindow* window)
    20292931{
    2030    ImGuiContext& g = *GImGui;
    2031    g.CurrentWindow = window;
    2032    if (window)
    2033       g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
    2034 }
    2035 
    2036 static void SetNavID(ImGuiID id, int nav_layer)
    2037 {
    2038    ImGuiContext& g = *GImGui;
    2039    IM_ASSERT(g.NavWindow);
    2040    IM_ASSERT(nav_layer == 0 || nav_layer == 1);
    2041    g.NavId = id;
    2042    g.NavWindow->NavLastIds[nav_layer] = id;
    2043 }
    2044 
    2045 static void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel)
    2046 {
    2047    ImGuiContext& g = *GImGui;
    2048    SetNavID(id, nav_layer);
    2049    g.NavWindow->NavRectRel[nav_layer] = rect_rel;
    2050    g.NavMousePosDirty = true;
    2051    g.NavDisableHighlight = false;
    2052    g.NavDisableMouseHover = true;
     2932    ImGuiContext& g = *GImGui;
     2933    g.CurrentWindow = window;
     2934    if (window)
     2935        g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
     2936}
     2937
     2938// Free up/compact internal window buffers, we can use this when a window becomes unused.
     2939// This is currently unused by the library, but you may call this yourself for easy GC.
     2940// Not freed:
     2941// - ImGuiWindow, ImGuiWindowSettings, Name
     2942// - StateStorage, ColumnsStorage (may hold useful data)
     2943// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
     2944void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
     2945{
     2946    window->MemoryCompacted = true;
     2947    window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
     2948    window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
     2949    window->IDStack.clear();
     2950    window->DrawList->_ClearFreeMemory();
     2951    window->DC.ChildWindows.clear();
     2952    window->DC.ItemFlagsStack.clear();
     2953    window->DC.ItemWidthStack.clear();
     2954    window->DC.TextWrapPosStack.clear();
     2955    window->DC.GroupStack.clear();
     2956}
     2957
     2958void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
     2959{
     2960    // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening.
     2961    // The other buffers tends to amortize much faster.
     2962    window->MemoryCompacted = false;
     2963    window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
     2964    window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
     2965    window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
    20532966}
    20542967
    20552968void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
    20562969{
    2057    ImGuiContext& g = *GImGui;
    2058    g.ActiveIdIsJustActivated = (g.ActiveId != id);
    2059    if (g.ActiveIdIsJustActivated)
    2060       g.ActiveIdTimer = 0.0f;
    2061    g.ActiveId = id;
    2062    g.ActiveIdAllowNavDirFlags = 0;
    2063    g.ActiveIdAllowOverlap = false;
    2064    g.ActiveIdWindow = window;
    2065    if (id)
    2066    {
    2067       g.ActiveIdIsAlive = true;
    2068       g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
    2069    }
    2070 }
    2071 
    2072 ImGuiID ImGui::GetActiveID()
    2073 {
    2074    ImGuiContext& g = *GImGui;
    2075    return g.ActiveId;
    2076 }
    2077 
    2078 void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
    2079 {
    2080    ImGuiContext& g = *GImGui;
    2081    IM_ASSERT(id != 0);
    2082 
    2083    // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it.
    2084    const int nav_layer = window->DC.NavLayerCurrent;
    2085    if (g.NavWindow != window)
    2086       g.NavInitRequest = false;
    2087    g.NavId = id;
    2088    g.NavWindow = window;
    2089    g.NavLayer = nav_layer;
    2090    window->NavLastIds[nav_layer] = id;
    2091    if (window->DC.LastItemId == id)
    2092       window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
    2093 
    2094    if (g.ActiveIdSource == ImGuiInputSource_Nav)
    2095       g.NavDisableMouseHover = true;
    2096    else
    2097       g.NavDisableHighlight = true;
     2970    ImGuiContext& g = *GImGui;
     2971    g.ActiveIdIsJustActivated = (g.ActiveId != id);
     2972    if (g.ActiveIdIsJustActivated)
     2973    {
     2974        g.ActiveIdTimer = 0.0f;
     2975        g.ActiveIdHasBeenPressedBefore = false;
     2976        g.ActiveIdHasBeenEditedBefore = false;
     2977        if (id != 0)
     2978        {
     2979            g.LastActiveId = id;
     2980            g.LastActiveIdTimer = 0.0f;
     2981        }
     2982    }
     2983    g.ActiveId = id;
     2984    g.ActiveIdAllowOverlap = false;
     2985    g.ActiveIdNoClearOnFocusLoss = false;
     2986    g.ActiveIdWindow = window;
     2987    g.ActiveIdHasBeenEditedThisFrame = false;
     2988    if (id)
     2989    {
     2990        g.ActiveIdIsAlive = id;
     2991        g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
     2992    }
     2993
     2994    // Clear declaration of inputs claimed by the widget
     2995    // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet)
     2996    g.ActiveIdUsingNavDirMask = 0x00;
     2997    g.ActiveIdUsingNavInputMask = 0x00;
     2998    g.ActiveIdUsingKeyInputMask = 0x00;
    20982999}
    20993000
    21003001void ImGui::ClearActiveID()
    21013002{
    2102    SetActiveID(0, NULL);
     3003    SetActiveID(0, NULL); // g.ActiveId = 0;
    21033004}
    21043005
    21053006void ImGui::SetHoveredID(ImGuiID id)
    21063007{
    2107    ImGuiContext& g = *GImGui;
    2108    g.HoveredId = id;
    2109    g.HoveredIdAllowOverlap = false;
    2110    g.HoveredIdTimer = (id != 0 && g.HoveredIdPreviousFrame == id) ? (g.HoveredIdTimer + g.IO.DeltaTime) : 0.0f;
     3008    ImGuiContext& g = *GImGui;
     3009    g.HoveredId = id;
     3010    g.HoveredIdAllowOverlap = false;
     3011    if (id != 0 && g.HoveredIdPreviousFrame != id)
     3012        g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
    21113013}
    21123014
    21133015ImGuiID ImGui::GetHoveredID()
    21143016{
    2115    ImGuiContext& g = *GImGui;
    2116    return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
     3017    ImGuiContext& g = *GImGui;
     3018    return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
    21173019}
    21183020
    21193021void ImGui::KeepAliveID(ImGuiID id)
    21203022{
    2121    ImGuiContext& g = *GImGui;
    2122    if (g.ActiveId == id)
    2123       g.ActiveIdIsAlive = true;
     3023    ImGuiContext& g = *GImGui;
     3024    if (g.ActiveId == id)
     3025        g.ActiveIdIsAlive = id;
     3026    if (g.ActiveIdPreviousFrame == id)
     3027        g.ActiveIdPreviousFrameIsAlive = true;
     3028}
     3029
     3030void ImGui::MarkItemEdited(ImGuiID id)
     3031{
     3032    // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
     3033    // 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.
     3034    ImGuiContext& g = *GImGui;
     3035    IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
     3036    IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
     3037    //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
     3038    g.ActiveIdHasBeenEditedThisFrame = true;
     3039    g.ActiveIdHasBeenEditedBefore = true;
     3040    g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
    21243041}
    21253042
    21263043static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
    21273044{
    2128    // An active popup disable hovering on other windows (apart from its own children)
    2129    // FIXME-OPT: This could be cached/stored within the window.
    2130    ImGuiContext& g = *GImGui;
    2131    if (g.NavWindow)
    2132       if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
    2133          if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
    2134          {
    2135             // For the purpose of those flags we differentiate "standard popup" from "modal popup"
    2136             // NB: The order of those two tests is important because Modal windows are also Popups.
    2137             if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
    2138                return false;
    2139             if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
    2140                return false;
    2141          }
    2142 
    2143    return true;
    2144 }
    2145 
    2146 // Advance cursor given item size for layout.
    2147 void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
    2148 {
    2149    ImGuiContext& g = *GImGui;
    2150    ImGuiWindow* window = g.CurrentWindow;
    2151    if (window->SkipItems)
    2152       return;
    2153 
    2154    // Always align ourselves on pixel boundaries
    2155    const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
    2156    const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
    2157    //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]
    2158    window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
    2159    window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));
    2160    window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
    2161    window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
    2162    //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
    2163 
    2164    window->DC.PrevLineHeight = line_height;
    2165    window->DC.PrevLineTextBaseOffset = text_base_offset;
    2166    window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f;
    2167 
    2168    // Horizontal layout mode
    2169    if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
    2170       SameLine();
    2171 }
    2172 
    2173 void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
    2174 {
    2175    ItemSize(bb.GetSize(), text_offset_y);
    2176 }
    2177 
    2178 static ImGuiDir NavScoreItemGetQuadrant(float dx, float dy)
    2179 {
    2180    if (fabsf(dx) > fabsf(dy))
    2181       return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
    2182    return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
    2183 }
    2184 
    2185 static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
    2186 {
    2187    if (a1 < b0)
    2188       return a1 - b0;
    2189    if (b1 < a0)
    2190       return a0 - b1;
    2191    return 0.0f;
    2192 }
    2193 
    2194 // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057
    2195 static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
    2196 {
    2197    ImGuiContext& g = *GImGui;
    2198    ImGuiWindow* window = g.CurrentWindow;
    2199    if (g.NavLayer != window->DC.NavLayerCurrent)
    2200       return false;
    2201 
    2202    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)
    2203    g.NavScoringCount++;
    2204 
    2205    // We perform scoring on items bounding box clipped by their parent window on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
    2206    if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
    2207    {
    2208       cand.Min.y = ImClamp(cand.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y);
    2209       cand.Max.y = ImClamp(cand.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y);
    2210    }
    2211    else
    2212    {
    2213       cand.Min.x = ImClamp(cand.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
    2214       cand.Max.x = ImClamp(cand.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
    2215    }
    2216 
    2217    // Compute distance between boxes
    2218    // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
    2219    float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
    2220    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
    2221    if (dby != 0.0f && dbx != 0.0f)
    2222       dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
    2223    float dist_box = fabsf(dbx) + fabsf(dby);
    2224 
    2225    // 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)
    2226    float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
    2227    float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
    2228    float dist_center = fabsf(dcx) + fabsf(dcy); // L1 metric (need this for our connectedness guarantee)
    2229 
    2230                                                 // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
    2231    ImGuiDir quadrant;
    2232    float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
    2233    if (dbx != 0.0f || dby != 0.0f)
    2234    {
    2235       // For non-overlapping boxes, use distance between boxes
    2236       dax = dbx;
    2237       day = dby;
    2238       dist_axial = dist_box;
    2239       quadrant = NavScoreItemGetQuadrant(dbx, dby);
    2240    }
    2241    else if (dcx != 0.0f || dcy != 0.0f)
    2242    {
    2243       // For overlapping boxes with different centers, use distance between centers
    2244       dax = dcx;
    2245       day = dcy;
    2246       dist_axial = dist_center;
    2247       quadrant = NavScoreItemGetQuadrant(dcx, dcy);
    2248    }
    2249    else
    2250    {
    2251       // 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)
    2252       quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
    2253    }
    2254 
    2255 #if IMGUI_DEBUG_NAV_SCORING
    2256    char buf[128];
    2257    if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max))
    2258    {
    2259       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]);
    2260       ImDrawList* draw_list = ImGui::GetOverlayDrawList();
    2261       draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100));
    2262       draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200));
    2263       draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max + ImGui::CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40, 0, 0, 150));
    2264       draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf);
    2265    }
    2266    else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
    2267    {
    2268       if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; }
    2269       if (quadrant == g.NavMoveDir)
    2270       {
    2271          ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
    2272          ImDrawList* draw_list = ImGui::GetOverlayDrawList();
    2273          draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200));
    2274          draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf);
    2275       }
    2276    }
    2277 #endif
    2278 
    2279    // Is it in the quadrant we're interesting in moving to?
    2280    bool new_best = false;
    2281    if (quadrant == g.NavMoveDir)
    2282    {
    2283       // Does it beat the current best candidate?
    2284       if (dist_box < result->DistBox)
    2285       {
    2286          result->DistBox = dist_box;
    2287          result->DistCenter = dist_center;
    2288          return true;
    2289       }
    2290       if (dist_box == result->DistBox)
    2291       {
    2292          // Try using distance between center points to break ties
    2293          if (dist_center < result->DistCenter)
    2294          {
    2295             result->DistCenter = dist_center;
    2296             new_best = true;
    2297          }
    2298          else if (dist_center == result->DistCenter)
    2299          {
    2300             // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
    2301             // (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),
    2302             // 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.
    2303             if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
    2304                new_best = true;
    2305          }
    2306       }
    2307    }
    2308 
    2309    // 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
    2310    // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
    2311    // 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.
    2312    // 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.
    2313    // Disabling it may however lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
    2314    if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)  // Check axial match
    2315       if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
    2316          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))
    2317          {
    2318             result->DistAxial = dist_axial;
    2319             new_best = true;
    2320          }
    2321 
    2322    return new_best;
    2323 }
    2324 
    2325 static void NavSaveLastChildNavWindow(ImGuiWindow* child_window)
    2326 {
    2327    ImGuiWindow* parent_window = child_window;
    2328    while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
    2329       parent_window = parent_window->ParentWindow;
    2330    if (parent_window && parent_window != child_window)
    2331       parent_window->NavLastChildNavWindow = child_window;
    2332 }
    2333 
    2334 // Call when we are expected to land on Layer 0 after FocusWindow()
    2335 static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window)
    2336 {
    2337    return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
    2338 }
    2339 
    2340 static void NavRestoreLayer(int layer)
    2341 {
    2342    ImGuiContext& g = *GImGui;
    2343    g.NavLayer = layer;
    2344    if (layer == 0)
    2345       g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
    2346    if (layer == 0 && g.NavWindow->NavLastIds[0] != 0)
    2347       SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]);
    2348    else
    2349       ImGui::NavInitWindow(g.NavWindow, true);
    2350 }
    2351 
    2352 static inline void NavUpdateAnyRequestFlag()
    2353 {
    2354    ImGuiContext& g = *GImGui;
    2355    g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
    2356    if (g.NavAnyRequest)
    2357       IM_ASSERT(g.NavWindow != NULL);
    2358 }
    2359 
    2360 static bool NavMoveRequestButNoResultYet()
    2361 {
    2362    ImGuiContext& g = *GImGui;
    2363    return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
    2364 }
    2365 
    2366 void ImGui::NavMoveRequestCancel()
    2367 {
    2368    ImGuiContext& g = *GImGui;
    2369    g.NavMoveRequest = false;
    2370    NavUpdateAnyRequestFlag();
    2371 }
    2372 
    2373 // We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
    2374 static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
    2375 {
    2376    ImGuiContext& g = *GImGui;
    2377    //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.
    2378    //    return;
    2379 
    2380    const ImGuiItemFlags item_flags = window->DC.ItemFlags;
    2381    const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
    2382    if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
    2383    {
    2384       // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
    2385       if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0)
    2386       {
    2387          g.NavInitResultId = id;
    2388          g.NavInitResultRectRel = nav_bb_rel;
    2389       }
    2390       if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus))
    2391       {
    2392          g.NavInitRequest = false; // Found a match, clear request
    2393          NavUpdateAnyRequestFlag();
    2394       }
    2395    }
    2396 
    2397    // Scoring for navigation
    2398    if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav))
    2399    {
    2400       ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
    2401 #if IMGUI_DEBUG_NAV_SCORING
    2402       // [DEBUG] Score all items in NavWindow at all times
    2403       if (!g.NavMoveRequest)
    2404          g.NavMoveDir = g.NavMoveDirLast;
    2405       bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest;
    2406 #else
    2407       bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb);
    2408 #endif
    2409       if (new_best)
    2410       {
    2411          result->ID = id;
    2412          result->ParentID = window->IDStack.back();
    2413          result->Window = window;
    2414          result->RectRel = nav_bb_rel;
    2415       }
    2416    }
    2417 
    2418    // Update window-relative bounding box of navigated item
    2419    if (g.NavId == id)
    2420    {
    2421       g.NavWindow = window;                                           // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
    2422       g.NavLayer = window->DC.NavLayerCurrent;
    2423       g.NavIdIsAlive = true;
    2424       g.NavIdTabCounter = window->FocusIdxTabCounter;
    2425       window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel;    // Store item bounding box (relative to window position)
    2426    }
    2427 }
    2428 
    2429 // Declare item bounding box for clipping and interaction.
    2430 // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
    2431 // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
    2432 bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
    2433 {
    2434    ImGuiContext& g = *GImGui;
    2435    ImGuiWindow* window = g.CurrentWindow;
    2436 
    2437    if (id != 0)
    2438    {
    2439       // Navigation processing runs prior to clipping early-out
    2440       //  (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
    2441       //  (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.
    2442       //      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.
    2443       //      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)
    2444       window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask;
    2445       if (g.NavId == id || g.NavAnyRequest)
    2446          if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
    2447             if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
    2448                NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id);
    2449    }
    2450 
    2451    window->DC.LastItemId = id;
    2452    window->DC.LastItemRect = bb;
    2453    window->DC.LastItemStatusFlags = 0;
    2454 
    2455    // Clipping test
    2456    const bool is_clipped = IsClippedEx(bb, id, false);
    2457    if (is_clipped)
    2458       return false;
    2459    //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
    2460 
    2461    // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
    2462    if (IsMouseHoveringRect(bb.Min, bb.Max))
    2463       window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
    2464    return true;
     3045    // An active popup disable hovering on other windows (apart from its own children)
     3046    // FIXME-OPT: This could be cached/stored within the window.
     3047    ImGuiContext& g = *GImGui;
     3048    if (g.NavWindow)
     3049        if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
     3050            if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
     3051            {
     3052                // For the purpose of those flags we differentiate "standard popup" from "modal popup"
     3053                // NB: The order of those two tests is important because Modal windows are also Popups.
     3054                if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
     3055                    return false;
     3056                if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
     3057                    return false;
     3058            }
     3059    return true;
    24653060}
    24663061
     
    24703065bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
    24713066{
    2472    ImGuiContext& g = *GImGui;
    2473    ImGuiWindow* window = g.CurrentWindow;
    2474    if (g.NavDisableMouseHover && !g.NavDisableHighlight)
    2475       return IsItemFocused();
    2476 
    2477    // Test for bounding box overlap, as updated as ItemAdd()
    2478    if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
    2479       return false;
    2480    IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0);   // Flags not supported by this function
    2481 
    2482                                                                                                 // Test if we are hovering the right window (our window could be behind another window)
    2483                                                                                                 // [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.
    2484                                                                                                 // 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.
    2485                                                                                                 //if (g.HoveredWindow != window)
    2486                                                                                                 //    return false;
    2487    if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
    2488       return false;
    2489 
    2490    // Test if another item is active (e.g. being dragged)
    2491    if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
    2492       if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
    2493          return false;
    2494 
    2495    // Test if interactions on this window are blocked by an active popup or modal
    2496    if (!IsWindowContentHoverable(window, flags))
    2497       return false;
    2498 
    2499    // Test if the item is disabled
    2500    if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
    2501       return false;
    2502 
    2503    // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case.
    2504    if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
    2505       return false;
    2506    return true;
     3067    ImGuiContext& g = *GImGui;
     3068    ImGuiWindow* window = g.CurrentWindow;
     3069    if (g.NavDisableMouseHover && !g.NavDisableHighlight)
     3070        return IsItemFocused();
     3071
     3072    // Test for bounding box overlap, as updated as ItemAdd()
     3073    if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
     3074        return false;
     3075    IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0);   // Flags not supported by this function
     3076
     3077    // Test if we are hovering the right window (our window could be behind another window)
     3078    // [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.
     3079    // 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.
     3080    //if (g.HoveredWindow != window)
     3081    //    return false;
     3082    if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
     3083        return false;
     3084
     3085    // Test if another item is active (e.g. being dragged)
     3086    if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
     3087        if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
     3088            return false;
     3089
     3090    // Test if interactions on this window are blocked by an active popup or modal.
     3091    // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here.
     3092    if (!IsWindowContentHoverable(window, flags))
     3093        return false;
     3094
     3095    // Test if the item is disabled
     3096    if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
     3097        return false;
     3098
     3099    // Special handling for calling after Begin() which represent the title bar or tab.
     3100    // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
     3101    if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
     3102        return false;
     3103    return true;
    25073104}
    25083105
     
    25103107bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
    25113108{
    2512    ImGuiContext& g = *GImGui;
    2513    if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
    2514       return false;
    2515 
    2516    ImGuiWindow* window = g.CurrentWindow;
    2517    if (g.HoveredWindow != window)
    2518       return false;
    2519    if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
    2520       return false;
    2521    if (!IsMouseHoveringRect(bb.Min, bb.Max))
    2522       return false;
    2523    if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default))
    2524       return false;
    2525    if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
    2526       return false;
    2527 
    2528    SetHoveredID(id);
    2529    return true;
     3109    ImGuiContext& g = *GImGui;
     3110    if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
     3111        return false;
     3112
     3113    ImGuiWindow* window = g.CurrentWindow;
     3114    if (g.HoveredWindow != window)
     3115        return false;
     3116    if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
     3117        return false;
     3118    if (!IsMouseHoveringRect(bb.Min, bb.Max))
     3119        return false;
     3120    if (g.NavDisableMouseHover)
     3121        return false;
     3122    if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (window->DC.ItemFlags & ImGuiItemFlags_Disabled))
     3123    {
     3124        g.HoveredIdDisabled = true;
     3125        return false;
     3126    }
     3127
     3128    // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level
     3129    // hover test in widgets code. We could also decide to split this function is two.
     3130    if (id != 0)
     3131    {
     3132        SetHoveredID(id);
     3133
     3134        // [DEBUG] Item Picker tool!
     3135        // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
     3136        // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
     3137        // items if we perform the test in ItemAdd(), but that would incur a small runtime cost.
     3138        // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd().
     3139        if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
     3140            GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
     3141        if (g.DebugItemPickerBreakId == id)
     3142            IM_DEBUG_BREAK();
     3143    }
     3144
     3145    return true;
    25303146}
    25313147
    25323148bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
    25333149{
    2534    ImGuiContext& g = *GImGui;
    2535    ImGuiWindow* window = g.CurrentWindow;
    2536    if (!bb.Overlaps(window->ClipRect))
    2537       if (id == 0 || id != g.ActiveId)
    2538          if (clip_even_when_logged || !g.LogEnabled)
     3150    ImGuiContext& g = *GImGui;
     3151    ImGuiWindow* window = g.CurrentWindow;
     3152    if (!bb.Overlaps(window->ClipRect))
     3153        if (id == 0 || (id != g.ActiveId && id != g.NavId))
     3154            if (clip_even_when_logged || !g.LogEnabled)
     3155                return true;
     3156    return false;
     3157}
     3158
     3159// This is also inlined in ItemAdd()
     3160// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect!
     3161void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags item_flags, const ImRect& item_rect)
     3162{
     3163    window->DC.LastItemId = item_id;
     3164    window->DC.LastItemStatusFlags = item_flags;
     3165    window->DC.LastItemRect = item_rect;
     3166}
     3167
     3168// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
     3169bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
     3170{
     3171    ImGuiContext& g = *GImGui;
     3172
     3173    // Increment counters
     3174    const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
     3175    window->DC.FocusCounterRegular++;
     3176    if (is_tab_stop)
     3177        window->DC.FocusCounterTabStop++;
     3178
     3179    // Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
     3180    // (Note that we can always TAB out of a widget that doesn't allow tabbing in)
     3181    if (g.ActiveId == id && g.FocusTabPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.FocusRequestNextWindow == NULL)
     3182    {
     3183        g.FocusRequestNextWindow = window;
     3184        g.FocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (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.
     3185    }
     3186
     3187    // Handle focus requests
     3188    if (g.FocusRequestCurrWindow == window)
     3189    {
     3190        if (window->DC.FocusCounterRegular == g.FocusRequestCurrCounterRegular)
    25393191            return true;
    2540    return false;
    2541 }
    2542 
    2543 bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
    2544 {
    2545    ImGuiContext& g = *GImGui;
    2546 
    2547    const bool allow_keyboard_focus = (window->DC.ItemFlags & (ImGuiItemFlags_AllowKeyboardFocus | ImGuiItemFlags_Disabled)) == ImGuiItemFlags_AllowKeyboardFocus;
    2548    window->FocusIdxAllCounter++;
    2549    if (allow_keyboard_focus)
    2550       window->FocusIdxTabCounter++;
    2551 
    2552    // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
    2553    // Note that we can always TAB out of a widget that doesn't allow tabbing in.
    2554    if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
    2555       window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
    2556 
    2557    if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
    2558       return true;
    2559    if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
    2560    {
    2561       g.NavJustTabbedId = id;
    2562       return true;
    2563    }
    2564 
    2565    return false;
     3192        if (is_tab_stop && window->DC.FocusCounterTabStop == g.FocusRequestCurrCounterTabStop)
     3193        {
     3194            g.NavJustTabbedId = id;
     3195            return true;
     3196        }
     3197
     3198        // If another item is about to be focused, we clear our own active id
     3199        if (g.ActiveId == id)
     3200            ClearActiveID();
     3201    }
     3202
     3203    return false;
    25663204}
    25673205
    25683206void ImGui::FocusableItemUnregister(ImGuiWindow* window)
    25693207{
    2570    window->FocusIdxAllCounter--;
    2571    window->FocusIdxTabCounter--;
    2572 }
    2573 
    2574 ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
    2575 {
    2576    ImGuiContext& g = *GImGui;
    2577    ImVec2 content_max;
    2578    if (size.x < 0.0f || size.y < 0.0f)
    2579       content_max = g.CurrentWindow->Pos + GetContentRegionMax();
    2580    if (size.x <= 0.0f)
    2581       size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
    2582    if (size.y <= 0.0f)
    2583       size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
    2584    return size;
     3208    window->DC.FocusCounterRegular--;
     3209    window->DC.FocusCounterTabStop--;
    25853210}
    25863211
    25873212float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
    25883213{
    2589    if (wrap_pos_x < 0.0f)
    2590       return 0.0f;
    2591 
    2592    ImGuiWindow* window = GetCurrentWindowRead();
    2593    if (wrap_pos_x == 0.0f)
    2594       wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
    2595    else if (wrap_pos_x > 0.0f)
    2596       wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
    2597 
    2598    return ImMax(wrap_pos_x - pos.x, 1.0f);
    2599 }
    2600 
    2601 //-----------------------------------------------------------------------------
    2602 
    2603 void* ImGui::MemAlloc(size_t sz)
    2604 {
    2605    GImAllocatorActiveAllocationsCount++;
    2606    return GImAllocatorAllocFunc(sz, GImAllocatorUserData);
    2607 }
    2608 
     3214    if (wrap_pos_x < 0.0f)
     3215        return 0.0f;
     3216
     3217    ImGuiContext& g = *GImGui;
     3218    ImGuiWindow* window = g.CurrentWindow;
     3219    if (wrap_pos_x == 0.0f)
     3220    {
     3221        // We could decide to setup a default wrapping max point for auto-resizing windows,
     3222        // or have auto-wrap (with unspecified wrapping pos) behave as a ContentSize extending function?
     3223        //if (window->Hidden && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize))
     3224        //    wrap_pos_x = ImMax(window->WorkRect.Min.x + g.FontSize * 10.0f, window->WorkRect.Max.x);
     3225        //else
     3226        wrap_pos_x = window->WorkRect.Max.x;
     3227    }
     3228    else if (wrap_pos_x > 0.0f)
     3229    {
     3230        wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
     3231    }
     3232
     3233    return ImMax(wrap_pos_x - pos.x, 1.0f);
     3234}
     3235
     3236// IM_ALLOC() == ImGui::MemAlloc()
     3237void* ImGui::MemAlloc(size_t size)
     3238{
     3239    if (ImGuiContext* ctx = GImGui)
     3240        ctx->IO.MetricsActiveAllocations++;
     3241    return GImAllocatorAllocFunc(size, GImAllocatorUserData);
     3242}
     3243
     3244// IM_FREE() == ImGui::MemFree()
    26093245void ImGui::MemFree(void* ptr)
    26103246{
    2611    if (ptr) GImAllocatorActiveAllocationsCount--;
    2612    return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
     3247    if (ptr)
     3248        if (ImGuiContext* ctx = GImGui)
     3249            ctx->IO.MetricsActiveAllocations--;
     3250    return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
    26133251}
    26143252
    26153253const char* ImGui::GetClipboardText()
    26163254{
    2617    return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
     3255    ImGuiContext& g = *GImGui;
     3256    return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : "";
    26183257}
    26193258
    26203259void ImGui::SetClipboardText(const char* text)
    26213260{
    2622    if (GImGui->IO.SetClipboardTextFn)
    2623       GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
     3261    ImGuiContext& g = *GImGui;
     3262    if (g.IO.SetClipboardTextFn)
     3263        g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text);
    26243264}
    26253265
    26263266const char* ImGui::GetVersion()
    26273267{
    2628    return IMGUI_VERSION;
    2629 }
    2630 
    2631 // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
     3268    return IMGUI_VERSION;
     3269}
     3270
     3271// Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself
    26323272// 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
    26333273ImGuiContext* ImGui::GetCurrentContext()
    26343274{
    2635    return GImGui;
     3275    return GImGui;
    26363276}
    26373277
     
    26393279{
    26403280#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
    2641    IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
     3281    IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
    26423282#else
    2643    GImGui = ctx;
     3283    GImGui = ctx;
    26443284#endif
    26453285}
    26463286
    2647 // Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
    2648 // 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.
    2649 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)
    2650 {
    2651    bool error = false;
    2652    if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatch version string!"); }
    2653    if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); }
    2654    if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); }
    2655    if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); }
    2656    if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); }
    2657    if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); }
    2658    return !error;
    2659 }
    2660 
    2661 void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data)
    2662 {
    2663    GImAllocatorAllocFunc = alloc_func;
    2664    GImAllocatorFreeFunc = free_func;
    2665    GImAllocatorUserData = user_data;
     3287void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
     3288{
     3289    GImAllocatorAllocFunc = alloc_func;
     3290    GImAllocatorFreeFunc = free_func;
     3291    GImAllocatorUserData = user_data;
    26663292}
    26673293
    26683294ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
    26693295{
    2670    ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
    2671    if (GImGui == NULL)
    2672       SetCurrentContext(ctx);
    2673    Initialize(ctx);
    2674    return ctx;
     3296    ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
     3297    if (GImGui == NULL)
     3298        SetCurrentContext(ctx);
     3299    Initialize(ctx);
     3300    return ctx;
    26753301}
    26763302
    26773303void ImGui::DestroyContext(ImGuiContext* ctx)
    26783304{
    2679    if (ctx == NULL)
    2680       ctx = GImGui;
    2681    Shutdown(ctx);
    2682    if (GImGui == ctx)
    2683       SetCurrentContext(NULL);
    2684    IM_DELETE(ctx);
     3305    if (ctx == NULL)
     3306        ctx = GImGui;
     3307    Shutdown(ctx);
     3308    if (GImGui == ctx)
     3309        SetCurrentContext(NULL);
     3310    IM_DELETE(ctx);
    26853311}
    26863312
    26873313ImGuiIO& ImGui::GetIO()
    26883314{
    2689    IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
    2690    return GImGui->IO;
    2691 }
    2692 
    2693 ImGuiStyle& ImGui::GetStyle()
    2694 {
    2695    IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
    2696    return GImGui->Style;
     3315    IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
     3316    return GImGui->IO;
    26973317}
    26983318
     
    27003320ImDrawData* ImGui::GetDrawData()
    27013321{
    2702    ImGuiContext& g = *GImGui;
    2703    return g.DrawData.Valid ? &g.DrawData : NULL;
    2704 }
    2705 
    2706 float ImGui::GetTime()
    2707 {
    2708    return GImGui->Time;
     3322    ImGuiContext& g = *GImGui;
     3323    return g.DrawData.Valid ? &g.DrawData : NULL;
     3324}
     3325
     3326double ImGui::GetTime()
     3327{
     3328    return GImGui->Time;
    27093329}
    27103330
    27113331int ImGui::GetFrameCount()
    27123332{
    2713    return GImGui->FrameCount;
    2714 }
    2715 
    2716 ImDrawList* ImGui::GetOverlayDrawList()
    2717 {
    2718    return &GImGui->OverlayDrawList;
     3333    return GImGui->FrameCount;
     3334}
     3335
     3336ImDrawList* ImGui::GetBackgroundDrawList()
     3337{
     3338    return &GImGui->BackgroundDrawList;
     3339}
     3340
     3341ImDrawList* ImGui::GetForegroundDrawList()
     3342{
     3343    return &GImGui->ForegroundDrawList;
    27193344}
    27203345
    27213346ImDrawListSharedData* ImGui::GetDrawListSharedData()
    27223347{
    2723    return &GImGui->DrawListSharedData;
    2724 }
    2725 
    2726 // This needs to be called before we submit any widget (aka in or before Begin)
    2727 void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
    2728 {
    2729    ImGuiContext& g = *GImGui;
    2730    IM_ASSERT(window == g.NavWindow);
    2731    bool init_for_nav = false;
    2732    if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
    2733       if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
    2734          init_for_nav = true;
    2735    if (init_for_nav)
    2736    {
    2737       SetNavID(0, g.NavLayer);
    2738       g.NavInitRequest = true;
    2739       g.NavInitRequestFromMove = false;
    2740       g.NavInitResultId = 0;
    2741       g.NavInitResultRectRel = ImRect();
    2742       NavUpdateAnyRequestFlag();
    2743    }
    2744    else
    2745    {
    2746       g.NavId = window->NavLastIds[0];
    2747    }
    2748 }
    2749 
    2750 static ImVec2 NavCalcPreferredRefPos()
    2751 {
    2752    ImGuiContext& g = *GImGui;
    2753    if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
    2754       return ImFloor(g.IO.MousePos);
    2755 
    2756    // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item
    2757    const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
    2758    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()));
    2759    ImRect visible_rect = GetViewportRect();
    2760    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.
    2761 }
    2762 
    2763 static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N)
    2764 {
    2765    ImGuiContext& g = *GImGui;
    2766    for (int i = g.Windows.Size - 1; i >= 0; i--)
    2767       if (g.Windows[i] == window)
    2768          return i;
    2769    return -1;
    2770 }
    2771 
    2772 static ImGuiWindow* FindWindowNavigable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
    2773 {
    2774    ImGuiContext& g = *GImGui;
    2775    for (int i = i_start; i >= 0 && i < g.Windows.Size && i != i_stop; i += dir)
    2776       if (ImGui::IsWindowNavFocusable(g.Windows[i]))
    2777          return g.Windows[i];
    2778    return NULL;
    2779 }
    2780 
    2781 float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
    2782 {
    2783    ImGuiContext& g = *GImGui;
    2784    if (mode == ImGuiInputReadMode_Down)
    2785       return g.IO.NavInputs[n];                         // Instant, read analog input (0.0f..1.0f, as provided by user)
    2786 
    2787    const float t = g.IO.NavInputsDownDuration[n];
    2788    if (t < 0.0f && mode == ImGuiInputReadMode_Released)  // Return 1.0f when just released, no repeat, ignore analog input.
    2789       return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
    2790    if (t < 0.0f)
    2791       return 0.0f;
    2792    if (mode == ImGuiInputReadMode_Pressed)               // Return 1.0f when just pressed, no repeat, ignore analog input.
    2793       return (t == 0.0f) ? 1.0f : 0.0f;
    2794    if (mode == ImGuiInputReadMode_Repeat)
    2795       return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f);
    2796    if (mode == ImGuiInputReadMode_RepeatSlow)
    2797       return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f);
    2798    if (mode == ImGuiInputReadMode_RepeatFast)
    2799       return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f);
    2800    return 0.0f;
    2801 }
    2802 
    2803 // Equivalent of IsKeyDown() for NavInputs[]
    2804 static bool IsNavInputDown(ImGuiNavInput n)
    2805 {
    2806    return GImGui->IO.NavInputs[n] > 0.0f;
    2807 }
    2808 
    2809 // Equivalent of IsKeyPressed() for NavInputs[]
    2810 static bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode)
    2811 {
    2812    return ImGui::GetNavInputAmount(n, mode) > 0.0f;
    2813 }
    2814 
    2815 static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode)
    2816 {
    2817    return (ImGui::GetNavInputAmount(n1, mode) + ImGui::GetNavInputAmount(n2, mode)) > 0.0f;
    2818 }
    2819 
    2820 ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor)
    2821 {
    2822    ImVec2 delta(0.0f, 0.0f);
    2823    if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
    2824       delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode));
    2825    if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
    2826       delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode));
    2827    if (dir_sources & ImGuiNavDirSourceFlags_PadLStick)
    2828       delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode));
    2829    if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow))
    2830       delta *= slow_factor;
    2831    if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast))
    2832       delta *= fast_factor;
    2833    return delta;
    2834 }
    2835 
    2836 static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
    2837 {
    2838    ImGuiContext& g = *GImGui;
    2839    IM_ASSERT(g.NavWindowingTarget);
    2840    if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
    2841       return;
    2842 
    2843    const int i_current = FindWindowIndex(g.NavWindowingTarget);
    2844    ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
    2845    if (!window_target)
    2846       window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir);
    2847    g.NavWindowingTarget = window_target;
    2848    g.NavWindowingToggleLayer = false;
    2849 }
    2850 
    2851 // Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer)
    2852 static void ImGui::NavUpdateWindowing()
    2853 {
    2854    ImGuiContext& g = *GImGui;
    2855    ImGuiWindow* apply_focus_window = NULL;
    2856    bool apply_toggle_layer = false;
    2857 
    2858    bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
    2859    bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
    2860    if (start_windowing_with_gamepad || start_windowing_with_keyboard)
    2861       if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1))
    2862       {
    2863          g.NavWindowingTarget = window->RootWindowForTabbing;
    2864          g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f;
    2865          g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
    2866          g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
    2867       }
    2868 
    2869    // Gamepad update
    2870    g.NavWindowingHighlightTimer += g.IO.DeltaTime;
    2871    if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad)
    2872    {
    2873       // 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
    2874       g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f));
    2875 
    2876       // Select window to focus
    2877       const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow);
    2878       if (focus_change_dir != 0)
    2879       {
    2880          NavUpdateWindowingHighlightWindow(focus_change_dir);
    2881          g.NavWindowingHighlightAlpha = 1.0f;
    2882       }
    2883 
    2884       // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most)
    2885       if (!IsNavInputDown(ImGuiNavInput_Menu))
    2886       {
    2887          g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore.
    2888          if (g.NavWindowingToggleLayer && g.NavWindow)
    2889             apply_toggle_layer = true;
    2890          else if (!g.NavWindowingToggleLayer)
    2891             apply_focus_window = g.NavWindowingTarget;
    2892          g.NavWindowingTarget = NULL;
    2893       }
    2894    }
    2895 
    2896    // Keyboard: Focus
    2897    if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard)
    2898    {
    2899       // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
    2900       g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f
    2901       if (IsKeyPressedMap(ImGuiKey_Tab, true))
    2902          NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1);
    2903       if (!g.IO.KeyCtrl)
    2904          apply_focus_window = g.NavWindowingTarget;
    2905    }
    2906 
    2907    // Keyboard: Press and Release ALT to toggle menu layer
    2908    // 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
    2909    if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released))
    2910       if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev))
    2911          apply_toggle_layer = true;
    2912 
    2913    // Move window
    2914    if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
    2915    {
    2916       ImVec2 move_delta;
    2917       if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift)
    2918          move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
    2919       if (g.NavInputSource == ImGuiInputSource_NavGamepad)
    2920          move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
    2921       if (move_delta.x != 0.0f || move_delta.y != 0.0f)
    2922       {
    2923          const float NAV_MOVE_SPEED = 800.0f;
    2924          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
    2925          g.NavWindowingTarget->Pos += move_delta * move_speed;
    2926          g.NavDisableMouseHover = true;
    2927          MarkIniSettingsDirty(g.NavWindowingTarget);
    2928       }
    2929    }
    2930 
    2931    // Apply final focus
    2932    if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindowForTabbing))
    2933    {
    2934       g.NavDisableHighlight = false;
    2935       g.NavDisableMouseHover = true;
    2936       apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
    2937       ClosePopupsOverWindow(apply_focus_window);
    2938       FocusWindow(apply_focus_window);
    2939       if (apply_focus_window->NavLastIds[0] == 0)
    2940          NavInitWindow(apply_focus_window, false);
    2941 
    2942       // If the window only has a menu layer, select it directly
    2943       if (apply_focus_window->DC.NavLayerActiveMask == (1 << 1))
    2944          g.NavLayer = 1;
    2945    }
    2946    if (apply_focus_window)
    2947       g.NavWindowingTarget = NULL;
    2948 
    2949    // Apply menu/layer toggle
    2950    if (apply_toggle_layer && g.NavWindow)
    2951    {
    2952       ImGuiWindow* new_nav_window = g.NavWindow;
    2953       while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
    2954          new_nav_window = new_nav_window->ParentWindow;
    2955       if (new_nav_window != g.NavWindow)
    2956       {
    2957          ImGuiWindow* old_nav_window = g.NavWindow;
    2958          FocusWindow(new_nav_window);
    2959          new_nav_window->NavLastChildNavWindow = old_nav_window;
    2960       }
    2961       g.NavDisableHighlight = false;
    2962       g.NavDisableMouseHover = true;
    2963       NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0);
    2964    }
    2965 }
    2966 
    2967 // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
    2968 static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel)
    2969 {
    2970    // Scroll to keep newly navigated item fully into view
    2971    ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1));
    2972    //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG]
    2973    if (window_rect_rel.Contains(item_rect_rel))
    2974       return;
    2975 
    2976    ImGuiContext& g = *GImGui;
    2977    if (window->ScrollbarX && item_rect_rel.Min.x < window_rect_rel.Min.x)
    2978    {
    2979       window->ScrollTarget.x = item_rect_rel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x;
    2980       window->ScrollTargetCenterRatio.x = 0.0f;
    2981    }
    2982    else if (window->ScrollbarX && item_rect_rel.Max.x >= window_rect_rel.Max.x)
    2983    {
    2984       window->ScrollTarget.x = item_rect_rel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x;
    2985       window->ScrollTargetCenterRatio.x = 1.0f;
    2986    }
    2987    if (item_rect_rel.Min.y < window_rect_rel.Min.y)
    2988    {
    2989       window->ScrollTarget.y = item_rect_rel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y;
    2990       window->ScrollTargetCenterRatio.y = 0.0f;
    2991    }
    2992    else if (item_rect_rel.Max.y >= window_rect_rel.Max.y)
    2993    {
    2994       window->ScrollTarget.y = item_rect_rel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y;
    2995       window->ScrollTargetCenterRatio.y = 1.0f;
    2996    }
    2997 
    2998    // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block)
    2999    ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
    3000    item_rect_rel.Translate(window->Scroll - next_scroll);
    3001 }
    3002 
    3003 static void ImGui::NavUpdate()
    3004 {
    3005    ImGuiContext& g = *GImGui;
    3006    g.IO.WantSetMousePos = false;
    3007 
    3008 #if 0
    3009    if (g.NavScoringCount > 0) printf("[%05d] 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);
     3348    return &GImGui->DrawListSharedData;
     3349}
     3350
     3351void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
     3352{
     3353    // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
     3354    // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
     3355    // This is because we want ActiveId to be set even when the window is not permitted to move.
     3356    ImGuiContext& g = *GImGui;
     3357    FocusWindow(window);
     3358    SetActiveID(window->MoveId, window);
     3359    g.NavDisableHighlight = true;
     3360    g.ActiveIdNoClearOnFocusLoss = true;
     3361    g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
     3362
     3363    bool can_move_window = true;
     3364    if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
     3365        can_move_window = false;
     3366    if (can_move_window)
     3367        g.MovingWindow = window;
     3368}
     3369
     3370// Handle mouse moving window
     3371// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
     3372// FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId.
     3373// This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs,
     3374// but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other.
     3375void ImGui::UpdateMouseMovingWindowNewFrame()
     3376{
     3377    ImGuiContext& g = *GImGui;
     3378    if (g.MovingWindow != NULL)
     3379    {
     3380        // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
     3381        // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
     3382        KeepAliveID(g.ActiveId);
     3383        IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
     3384        ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
     3385        if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
     3386        {
     3387            ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
     3388            if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
     3389            {
     3390                MarkIniSettingsDirty(moving_window);
     3391                SetWindowPos(moving_window, pos, ImGuiCond_Always);
     3392            }
     3393            FocusWindow(g.MovingWindow);
     3394        }
     3395        else
     3396        {
     3397            ClearActiveID();
     3398            g.MovingWindow = NULL;
     3399        }
     3400    }
     3401    else
     3402    {
     3403        // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
     3404        if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
     3405        {
     3406            KeepAliveID(g.ActiveId);
     3407            if (!g.IO.MouseDown[0])
     3408                ClearActiveID();
     3409        }
     3410    }
     3411}
     3412
     3413// Initiate moving window when clicking on empty space or title bar.
     3414// Handle left-click and right-click focus.
     3415void ImGui::UpdateMouseMovingWindowEndFrame()
     3416{
     3417    ImGuiContext& g = *GImGui;
     3418    if (g.ActiveId != 0 || g.HoveredId != 0)
     3419        return;
     3420
     3421    // Unless we just made a window/popup appear
     3422    if (g.NavWindow && g.NavWindow->Appearing)
     3423        return;
     3424
     3425    // Click on empt