Bladeren bron

Updated ImGui.

Branimir Karadžić 10 jaren geleden
bovenliggende
commit
488ebe2e1e

+ 102 - 74
3rdparty/ocornut-imgui/imgui.cpp

@@ -2,7 +2,7 @@
 // Main code & documentation
 // Main code & documentation
 
 
 // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
 // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
-// Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
+// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
 // Get latest version at https://github.com/ocornut/imgui
 // Get latest version at https://github.com/ocornut/imgui
 // Releases change-log at https://github.com/ocornut/imgui/releases
 // Releases change-log at https://github.com/ocornut/imgui/releases
 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
@@ -76,18 +76,20 @@
  - read the FAQ below this section!
  - read the FAQ below this section!
  - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
  - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
  - call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
  - call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
- - see examples/ folder for standalone sample applications. e.g. examples/opengl_example/
+ - see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first at it is the simplest.
  - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
  - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme).
 
 
  - getting started:
  - getting started:
-   - initialisation: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the 'Settings' data.
+   - init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'.
+   - init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory.
    - every frame:
    - every frame:
-      1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the 'Input' data, then call ImGui::NewFrame().
-      2/ use any ImGui function you want between NewFrame() and Render()
-      3/ ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
+      1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input'
+      2/ call ImGui::NewFrame().
+      3/ use any ImGui function you want between NewFrame() and Render()
+      4/ call ImGui::Render() to render all the accumulated command-lists. it will call your RenderDrawListFn handler that you set in the IO structure.
    - all rendering information are stored into command-lists until ImGui::Render() is called.
    - all rendering information are stored into command-lists until ImGui::Render() is called.
    - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
    - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you must provide.
-   - effectively it means you can create widgets at any time in your code, regardless of "update" vs "render" considerations.
+   - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases.
    - refer to the examples applications in the examples/ folder for instruction on how to setup your code.
    - refer to the examples applications in the examples/ folder for instruction on how to setup your code.
    - a typical application skeleton may be:
    - a typical application skeleton may be:
 
 
@@ -100,32 +102,34 @@
         // TODO: Fill others settings of the io structure
         // TODO: Fill others settings of the io structure
 
 
         // Load texture atlas
         // Load texture atlas
+        // There is a default font so you don't need to care about choosing a font yet
         unsigned char* pixels;
         unsigned char* pixels;
-        int width, height, bytes_per_pixels;
-        io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height, &bytes_per_pixels);
-        // TODO: copy texture to graphics memory.
-        // TODO: store your texture pointer/identifier in 'io.Fonts->TexID'
+        int width, height;
+        io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);
+        // TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system 
+        // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'
 
 
         // Application main loop
         // Application main loop
         while (true)
         while (true)
         {
         {
-            // 1) get low-level input
-            // e.g. on Win32, GetKeyboardState(), or poll your events, etc.
-
-            // 2) TODO: fill all fields of IO structure and call NewFrame
+            // 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.)
+            // TODO: fill all fields of IO structure and call NewFrame
             ImGuiIO& io = ImGui::GetIO();
             ImGuiIO& io = ImGui::GetIO();
             io.DeltaTime = 1.0f/60.0f;
             io.DeltaTime = 1.0f/60.0f;
             io.MousePos = mouse_pos;
             io.MousePos = mouse_pos;
             io.MouseDown[0] = mouse_button_0;
             io.MouseDown[0] = mouse_button_0;
+            io.MouseDown[1] = mouse_button_1;
             io.KeysDown[i] = ...
             io.KeysDown[i] = ...
+
+            // 2) call NewFrame(), after this point you can use ImGui::* functions anytime
             ImGui::NewFrame();
             ImGui::NewFrame();
 
 
-            // 3) most of your application code here - you can use any of ImGui::* functions at any point in the frame
+            // 3) most of your application code here
             ImGui::Begin("My window");
             ImGui::Begin("My window");
             ImGui::Text("Hello, world.");
             ImGui::Text("Hello, world.");
             ImGui::End();
             ImGui::End();
-            GameUpdate();
-            GameRender();
+            MyGameUpdate(); // may use ImGui functions
+            MyGameRender(); // may use ImGui functions
 
 
             // 4) render & swap video buffers
             // 4) render & swap video buffers
             ImGui::Render();
             ImGui::Render();
@@ -410,6 +414,7 @@
  - window: get size/pos helpers given names (see discussion in #249)
  - window: get size/pos helpers given names (see discussion in #249)
  - window: a collapsed window can be stuck behind the main menu bar?
  - window: a collapsed window can be stuck behind the main menu bar?
  - window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
  - window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
+ - window: consider renaming "GetWindowFont" which conflict with old Windows #define (#340)
  - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
  - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
  - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
  - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
 !- scrolling: allow immediately effective change of scroll if we haven't appended items yet
 !- scrolling: allow immediately effective change of scroll if we haven't appended items yet
@@ -439,6 +444,8 @@
  - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
  - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) (#125)
  - columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
  - columns: columns header to act as button (~sort op) and allow resize/reorder (#125)
  - columns: user specify columns size (#125)
  - columns: user specify columns size (#125)
+ - columns: flag to add horizontal separator above/below?
+ - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets)
  - combo: sparse combo boxes (via function call?)
  - combo: sparse combo boxes (via function call?)
  - combo: contents should extends to fit label if combo widget is small
  - combo: contents should extends to fit label if combo widget is small
  - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
  - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
@@ -475,12 +482,14 @@
  - tree node / optimization: avoid formatting when clipped.
  - tree node / optimization: avoid formatting when clipped.
  - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
  - tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
  - tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
  - tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
+ - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
  - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
  - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
  - settings: write more decent code to allow saving/loading new fields
  - settings: write more decent code to allow saving/loading new fields
  - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
  - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file
  - style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
  - style: store rounded corners in texture to use 1 quad per corner (filled and wireframe). so rounding have minor cost.
  - style: color-box not always square?
  - style: color-box not always square?
  - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
  - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
+ - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
  - text: simple markup language for color change?
  - text: simple markup language for color change?
  - font: helper to add glyph redirect/replacements (e.g. redirect alternate apostrophe unicode code points to ascii one, etc.)
  - font: helper to add glyph redirect/replacements (e.g. redirect alternate apostrophe unicode code points to ascii one, etc.)
  - log: LogButtons() options for specifying depth and/or hiding depth slider
  - log: LogButtons() options for specifying depth and/or hiding depth slider
@@ -1597,7 +1606,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     g.ActiveId = id;
     g.ActiveId = id;
-    g.ActiveIdAllowHoveringOthers = false;
+    g.ActiveIdAllowOverlap = false;
     g.ActiveIdIsJustActivated = true;
     g.ActiveIdIsJustActivated = true;
     g.ActiveIdWindow = window;
     g.ActiveIdWindow = window;
 }
 }
@@ -1606,7 +1615,7 @@ void ImGui::SetHoveredID(ImGuiID id)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     g.HoveredId = id;
     g.HoveredId = id;
-    g.HoveredIdAllowHoveringOthers = false;
+    g.HoveredIdAllowOverlap = false;
 }
 }
 
 
 void ImGui::KeepAliveID(ImGuiID id)
 void ImGui::KeepAliveID(ImGuiID id)
@@ -1667,7 +1676,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
         window->DC.LastItemHoveredRect = true;
         window->DC.LastItemHoveredRect = true;
         window->DC.LastItemHoveredAndUsable = false;
         window->DC.LastItemHoveredAndUsable = false;
         if (g.HoveredRootWindow == window->RootWindow)
         if (g.HoveredRootWindow == window->RootWindow)
-            if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowHoveringOthers || (g.ActiveId == window->MoveID))
+            if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveID))
                 if (IsWindowContentHoverable(window))
                 if (IsWindowContentHoverable(window))
                     window->DC.LastItemHoveredAndUsable = true;
                     window->DC.LastItemHoveredAndUsable = true;
     }
     }
@@ -1696,11 +1705,11 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when
 bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
 bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
-    if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowHoveringOthers)
+    if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap)
     {
     {
         ImGuiWindow* window = GetCurrentWindowRead();
         ImGuiWindow* window = GetCurrentWindowRead();
         if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
         if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
-            if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowHoveringOthers) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
+            if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
                 if (IsWindowContentHoverable(g.HoveredRootWindow))
                 if (IsWindowContentHoverable(g.HoveredRootWindow))
                     return true;
                     return true;
     }
     }
@@ -1848,11 +1857,11 @@ void ImGui::NewFrame()
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
 
 
     // Check user data
     // Check user data
-    IM_ASSERT(g.IO.DeltaTime >= 0.0f);
+    IM_ASSERT(g.IO.DeltaTime >= 0.0f);               // Need a positive DeltaTime (zero is tolerated but will cause some timing issues)
     IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
     IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
     IM_ASSERT(g.IO.Fonts->Fonts.Size > 0);           // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
     IM_ASSERT(g.IO.Fonts->Fonts.Size > 0);           // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
     IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded());     // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
     IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded());     // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
-    IM_ASSERT(g.Style.CurveTessellationTol > 0.0f);  // Invalid
+    IM_ASSERT(g.Style.CurveTessellationTol > 0.0f);  // Invalid style setting
 
 
     if (!g.Initialized)
     if (!g.Initialized)
     {
     {
@@ -1928,7 +1937,7 @@ void ImGui::NewFrame()
     // Clear reference to active widget if the widget isn't alive anymore
     // Clear reference to active widget if the widget isn't alive anymore
     g.HoveredIdPreviousFrame = g.HoveredId;
     g.HoveredIdPreviousFrame = g.HoveredId;
     g.HoveredId = 0;
     g.HoveredId = 0;
-    g.HoveredIdAllowHoveringOthers = false;
+    g.HoveredIdAllowOverlap = false;
     if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
     if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
         SetActiveID(0);
         SetActiveID(0);
     g.ActiveIdPreviousFrame = g.ActiveId;
     g.ActiveIdPreviousFrame = g.ActiveId;
@@ -1982,6 +1991,7 @@ void ImGui::NewFrame()
     g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
     g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
     g.MouseCursor = ImGuiMouseCursor_Arrow;
     g.MouseCursor = ImGuiMouseCursor_Arrow;
     g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
     g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
+    g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
 
 
     // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
     // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
     if (mouse_owned_by_application)
     if (mouse_owned_by_application)
@@ -2269,8 +2279,7 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDr
         // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
         // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
         const unsigned long long int max_vtx_idx = (unsigned long long int)1L << (sizeof(ImDrawIdx)*8);
         const unsigned long long int max_vtx_idx = (unsigned long long int)1L << (sizeof(ImDrawIdx)*8);
         (void)max_vtx_idx;
         (void)max_vtx_idx;
-        IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx);
-        (void)max_vtx_idx;
+        IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= max_vtx_idx); // Too many vertices in same ImDrawList
 
 
         GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
         GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
         GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
         GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
@@ -2331,8 +2340,15 @@ void ImGui::EndFrame()
         ImGui::EndTooltip();
         ImGui::EndTooltip();
     }
     }
 
 
+    // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
+    if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)
+    {
+        g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);   
+        g.OsImePosSet = g.OsImePosRequest;
+    }
+
     // Hide implicit "Debug" window if it hasn't been used
     // Hide implicit "Debug" window if it hasn't been used
-    IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin/End
+    IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin()/End() calls
     if (g.CurrentWindow && !g.CurrentWindow->Accessed)
     if (g.CurrentWindow && !g.CurrentWindow->Accessed)
         g.CurrentWindow->Active = false;
         g.CurrentWindow->Active = false;
     ImGui::End();
     ImGui::End();
@@ -2368,9 +2384,8 @@ void ImGui::EndFrame()
     for (int i = 0; i != g.Windows.Size; i++)
     for (int i = 0; i != g.Windows.Size; i++)
     {
     {
         ImGuiWindow* window = g.Windows[i];
         ImGuiWindow* window = g.Windows[i];
-        if (window->Flags & ImGuiWindowFlags_ChildWindow)       // if a child is active its parent will add it
-            if (window->Active)
-                continue;
+        if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))       // if a child is active its parent will add it
+            continue;
         AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
         AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
     }
     }
     IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong
     IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong
@@ -2602,6 +2617,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
     }
     }
 }
 }
 
 
+// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
 void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align, const ImVec2* clip_min, const ImVec2* clip_max)
 void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, ImGuiAlign align, const ImVec2* clip_min, const ImVec2* clip_max)
 {
 {
     // Hide anything after a '##' string
     // Hide anything after a '##' string
@@ -3011,6 +3027,16 @@ bool ImGui::IsItemVisible()
     return r.Overlaps(window->DC.LastItemRect);
     return r.Overlaps(window->DC.LastItemRect);
 }
 }
 
 
+// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
+void ImGui::SetItemAllowOverlap()
+{
+    ImGuiState& g = *GImGui;
+    if (g.HoveredId == g.CurrentWindow->DC.LastItemID)
+        g.HoveredIdAllowOverlap = true;
+    if (g.ActiveId == g.CurrentWindow->DC.LastItemID)
+        g.ActiveIdAllowOverlap = true;
+}
+
 ImVec2 ImGui::GetItemRectMin()
 ImVec2 ImGui::GetItemRectMin()
 {
 {
     ImGuiWindow* window = GetCurrentWindowRead();
     ImGuiWindow* window = GetCurrentWindowRead();
@@ -3069,7 +3095,7 @@ void ImGui::BeginTooltip()
 
 
 void ImGui::EndTooltip()
 void ImGui::EndTooltip()
 {
 {
-    IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
+    IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);   // Mismatched BeginTooltip()/EndTooltip() calls
     ImGui::End();
     ImGui::End();
 }
 }
 
 
@@ -3238,7 +3264,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e
 void ImGui::EndPopup()
 void ImGui::EndPopup()
 {
 {
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
-    IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);
+    IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup);  // Mismatched BeginPopup()/EndPopup() calls
     IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);
     IM_ASSERT(GImGui->CurrentPopupStack.Size > 0);
     ImGui::End();
     ImGui::End();
     if (!(window->Flags & ImGuiWindowFlags_Modal))
     if (!(window->Flags & ImGuiWindowFlags_Modal))
@@ -3316,7 +3342,7 @@ void ImGui::EndChild()
 {
 {
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
 
 
-    IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
+    IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);   // Mismatched BeginChild()/EndChild() callss
     if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
     if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
     {
     {
         ImGui::End();
         ImGui::End();
@@ -4261,7 +4287,7 @@ float ImGui::CalcItemWidth()
 static void SetCurrentFont(ImFont* font)
 static void SetCurrentFont(ImFont* font)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
-    IM_ASSERT(font && font->IsLoaded());
+    IM_ASSERT(font && font->IsLoaded());    // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
     IM_ASSERT(font->Scale > 0.0f);
     IM_ASSERT(font->Scale > 0.0f);
     g.Font = font;
     g.Font = font;
     g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
     g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
@@ -5533,6 +5559,7 @@ bool ImGui::TreeNodeBehaviorIsOpened(ImGuiID id, ImGuiTreeNodeFlags flags)
     return opened;
     return opened;
 }
 }
 
 
+// FIXME: Split into CollapsingHeader(label, default_open?) and TreeNodeBehavior(label), obsolete the 4 parameters function.
 bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
 bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display_frame, bool default_open)
 {
 {
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -5541,6 +5568,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
 
 
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     const ImGuiStyle& style = g.Style;
     const ImGuiStyle& style = g.Style;
+    const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
 
 
     IM_ASSERT(str_id != NULL || label != NULL);
     IM_ASSERT(str_id != NULL || label != NULL);
     if (str_id == NULL)
     if (str_id == NULL)
@@ -5548,27 +5576,27 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
     if (label == NULL)
     if (label == NULL)
         label = str_id;
         label = str_id;
     const ImGuiID id = window->GetID(str_id);
     const ImGuiID id = window->GetID(str_id);
-
-    // Framed header expand a little outside the default padding
-    const ImVec2 window_padding = window->WindowPadding;
     const ImVec2 label_size = CalcTextSize(label, NULL, true);
     const ImVec2 label_size = CalcTextSize(label, NULL, true);
-    const ImVec2 pos_min = window->DC.CursorPos;
-    const ImVec2 pos_max = window->Pos + GetContentRegionMax();
-    ImRect bb = ImRect(pos_min, ImVec2(pos_max.x, pos_min.y + label_size.y));
+
+    // We vertically grow up to current line height up the typical widget height.
+    const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y);
+    const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + g.Style.FramePadding.y*2), label_size.y + padding.y*2);
+    ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
     if (display_frame)
     if (display_frame)
     {
     {
-        bb.Min.x -= (float)(int)(window_padding.x*0.5f) - 1;
-        bb.Max.x += (float)(int)(window_padding.x*0.5f) - 1;
-        bb.Max.y += style.FramePadding.y * 2;
+        // Framed header expand a little outside the default padding
+        bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
+        bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
     }
     }
 
 
-    const float collapser_width = g.FontSize + style.FramePadding.x*2;
-    const ImRect text_bb(bb.Min, bb.Min + ImVec2(collapser_width + style.FramePadding.x*2*0 + (label_size.x > 0.0f ? label_size.x : 0.0f), label_size.y));
-    ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y), display_frame ? style.FramePadding.y : 0.0f);
+    const float collapser_width = g.FontSize + padding.x*2;
+    const float text_width = collapser_width + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f);   // Include collapser
+    ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
 
 
-    const ImRect interact_bb = display_frame ? bb : ImRect(text_bb.Min, text_bb.Max + ImVec2(style.FramePadding.x*2,0.0f)); // FIXME
+    // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
+    // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not)
+    const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y);
     bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
     bool opened = TreeNodeBehaviorIsOpened(id, (default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0) | (display_frame ? ImGuiTreeNodeFlags_NoAutoExpandOnLog : 0));
-
     if (!ItemAdd(interact_bb, &id))
     if (!ItemAdd(interact_bb, &id))
         return opened;
         return opened;
 
 
@@ -5582,22 +5610,24 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
 
 
     // Render
     // Render
     const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
     const ImU32 col = window->Color((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+    const ImVec2 text_pos = bb.Min + padding + ImVec2(collapser_width, text_base_offset_y);
     if (display_frame)
     if (display_frame)
     {
     {
         // Framed type
         // Framed type
         RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
         RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
-        RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true);
+        RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), opened, 1.0f, true);
         if (g.LogEnabled)
         if (g.LogEnabled)
         {
         {
             // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
             // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
             const char log_prefix[] = "\n##";
             const char log_prefix[] = "\n##";
-            LogRenderedText(bb.Min + style.FramePadding, log_prefix, log_prefix+3);
+            const char log_suffix[] = "##";
+            LogRenderedText(text_pos, log_prefix, log_prefix+3);
+            RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
+            LogRenderedText(text_pos, log_suffix+1, log_suffix+3);
         }
         }
-        RenderTextClipped(bb.Min + style.FramePadding + ImVec2(collapser_width,0), bb.Max, label, NULL, &label_size);
-        if (g.LogEnabled)
+        else
         {
         {
-            const char log_suffix[] = "##";
-            LogRenderedText(bb.Min + style.FramePadding, log_suffix, log_suffix+2);
+            RenderTextClipped(text_pos, bb.Max, label, NULL, &label_size);
         }
         }
     }
     }
     else
     else
@@ -5605,10 +5635,11 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display
         // Unframed typed for tree nodes
         // Unframed typed for tree nodes
         if (hovered)
         if (hovered)
             RenderFrame(bb.Min, bb.Max, col, false);
             RenderFrame(bb.Min, bb.Max, col, false);
-        RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, g.FontSize*0.15f), opened, 0.70f, false);
+
+        RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), opened, 0.70f, false);
         if (g.LogEnabled)
         if (g.LogEnabled)
-            LogRenderedText(bb.Min, ">");
-        RenderText(bb.Min + ImVec2(collapser_width,0), label);
+            LogRenderedText(text_pos, ">");
+        RenderText(text_pos, label);
     }
     }
 
 
     return opened;
     return opened;
@@ -7109,7 +7140,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
 }
 }
 
 
 // Edit a string of text
 // Edit a string of text
-// FIXME: This is rather complex partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. 
+// FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188
 bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
 bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
 {
 {
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -7128,7 +7159,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
     const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
     const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
     const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
     const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
 
 
-    ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
+    const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
     ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
     ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), is_multiline ? ImGui::GetTextLineHeight() * 8.0f : label_size.y); // Arbitrary default of 8 lines high for multi-line
     const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
     const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size + style.FramePadding*2.0f);
     const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
     const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
@@ -7197,7 +7228,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         {
         {
             // Start edition
             // Start edition
             // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
             // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
-            // From the moment we focused we are ignoring the content of 'buf'
+            // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
             const int prev_len_w = edit_state.CurLenW;
             const int prev_len_w = edit_state.CurLenW;
             edit_state.Text.resize(buf_size+1);        // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
             edit_state.Text.resize(buf_size+1);        // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
             edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
             edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
@@ -7205,7 +7236,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
             const char* buf_end = NULL;
             const char* buf_end = NULL;
             edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
             edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
             edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
             edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImFormatString() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
-            edit_state.InputCursorScreenPos = ImVec2(-1.f, -1.f);
             edit_state.CursorAnimReset();
             edit_state.CursorAnimReset();
 
 
             // Preserve cursor position and undo/redo stack if we come back to same widget
             // Preserve cursor position and undo/redo stack if we come back to same widget
@@ -7259,8 +7289,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         edit_state.BufSizeA = buf_size;
         edit_state.BufSizeA = buf_size;
 
 
         // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
         // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
-        // Down the line we should have a cleaner concept of focused vs active in the library.
-        g.ActiveIdAllowHoveringOthers = !io.MouseDown[0];
+        // Down the line we should have a cleaner library-wide concept of Selected vs Active.
+        g.ActiveIdAllowOverlap = !io.MouseDown[0];
 
 
         // Edit in progress
         // Edit in progress
         const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
         const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
@@ -7407,9 +7437,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         else
         else
         {
         {
             // Apply new value immediately - copy modified buffer back
             // Apply new value immediately - copy modified buffer back
-            // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer
-            // FIXME: We actually always render 'buf' when calling DrawList->AddText
-            // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks
+            // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
+            // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
+            // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
             if (is_editable)
             if (is_editable)
             {
             {
                 edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
                 edit_state.TempTextBuffer.resize(edit_state.Text.Size * 4);
@@ -7624,11 +7654,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         if (cursor_is_visible)
         if (cursor_is_visible)
             draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
             draw_window->DrawList->AddLine(cursor_screen_pos + ImVec2(0.0f,-g.FontSize+0.5f), cursor_screen_pos + ImVec2(0.0f,-1.5f), window->Color(ImGuiCol_Text));
 
 
-        // Notify OS of text input position for advanced IME
-        if (is_editable && io.ImeSetInputScreenPosFn && ImLengthSqr(edit_state.InputCursorScreenPos - cursor_screen_pos) > 0.0001f)
-            io.ImeSetInputScreenPosFn((int)cursor_screen_pos.x - 1, (int)(cursor_screen_pos.y - g.FontSize));   // -1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.
-
-        edit_state.InputCursorScreenPos = cursor_screen_pos;
+        // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
+        if (is_editable)
+            g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);    
     }
     }
     else
     else
     {
     {
@@ -8650,7 +8678,7 @@ void ImGui::EndGroup()
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiStyle& style = ImGui::GetStyle();
     ImGuiStyle& style = ImGui::GetStyle();
 
 
-    IM_ASSERT(!window->DC.GroupStack.empty());
+    IM_ASSERT(!window->DC.GroupStack.empty());	// Mismatched BeginGroup()/EndGroup() calls
 
 
     ImGuiGroupData& group_data = window->DC.GroupStack.back();
     ImGuiGroupData& group_data = window->DC.GroupStack.back();
 
 

+ 23 - 13
3rdparty/ocornut-imgui/imgui_demo.cpp

@@ -226,7 +226,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
             {
             {
                 ImFont* font = atlas->Fonts[i];
                 ImFont* font = atlas->Fonts[i];
                 ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
                 ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
-                ImGui::TreePush((void*)intptr_t(i));
+                ImGui::TreePush((void*)(intptr_t)i);
                 if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } }
                 if (i > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { atlas->Fonts[i] = atlas->Fonts[0]; atlas->Fonts[0] = font; } }
                 ImGui::PushFont(font);
                 ImGui::PushFont(font);
                 ImGui::Text("The quick brown fox jumps over the lazy dog");
                 ImGui::Text("The quick brown fox jumps over the lazy dog");
@@ -264,7 +264,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
         {
         {
             for (int i = 0; i < 5; i++)
             for (int i = 0; i < 5; i++)
             {
             {
-                if (ImGui::TreeNode((void*)intptr_t(i), "Child %d", i))
+                if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
                 {
                 {
                     ImGui::Text("blah blah");
                     ImGui::Text("blah blah");
                     ImGui::SameLine();
                     ImGui::SameLine();
@@ -779,7 +779,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
             ImGui::TreePop();
             ImGui::TreePop();
         }
         }
 
 
-        if (ImGui::TreeNode("Widgets Alignment"))
+        if (ImGui::TreeNode("Widgets Width"))
         {
         {
             static float f = 0.0f;
             static float f = 0.0f;
             ImGui::Text("PushItemWidth(100)");
             ImGui::Text("PushItemWidth(100)");
@@ -950,6 +950,17 @@ void ImGui::ShowTestWindow(bool* p_opened)
             ImGui::Text("Widget"); ImGui::SameLine();
             ImGui::Text("Widget"); ImGui::SameLine();
             ImGui::SmallButton("Widget");
             ImGui::SmallButton("Widget");
 
 
+            // Tree
+            const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
+            ImGui::Button("Button##1"); 
+            ImGui::SameLine(0.0f, spacing); 
+            if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }    // Dummy tree data
+
+            ImGui::AlignFirstTextHeightToWidgets();         // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
+            bool tree_opened = ImGui::TreeNode("Node##2");  // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
+            ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
+            if (tree_opened) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }   // Dummy tree data
+
             ImGui::TreePop();
             ImGui::TreePop();
         }
         }
 
 
@@ -969,7 +980,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
                 if (i > 0) ImGui::SameLine();
                 if (i > 0) ImGui::SameLine();
                 ImGui::BeginGroup();
                 ImGui::BeginGroup();
                 ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
                 ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
-                ImGui::BeginChild(ImGui::GetID((void*)intptr_t(i)), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
+                ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
                 if (scroll_to)
                 if (scroll_to)
                     ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
                     ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
                 for (int line = 0; line < 100; line++)
                 for (int line = 0; line < 100; line++)
@@ -1038,13 +1049,13 @@ void ImGui::ShowTestWindow(bool* p_opened)
             static ImVec2 size(100, 100), offset(50, 20);
             static ImVec2 size(100, 100), offset(50, 20);
             ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
             ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
             ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
             ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
-            ImGui::DragFloat2("offset", (float*)&offset, 0.5f, -200, 200.0f, "%.0f");
+            ImGui::TextWrapped("(Click and drag)");
             ImVec2 pos = ImGui::GetCursorScreenPos();
             ImVec2 pos = ImGui::GetCursorScreenPos();
             ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
             ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
-            ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
-            ImGui::GetWindowDrawList()->AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
             ImGui::InvisibleButton("##dummy", size);
             ImGui::InvisibleButton("##dummy", size);
             if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
             if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
+            ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
+            ImGui::GetWindowDrawList()->AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
             ImGui::TreePop();
             ImGui::TreePop();
         }
         }
     }
     }
@@ -1328,9 +1339,9 @@ void ImGui::ShowTestWindow(bool* p_opened)
             ImGui::TreePop();
             ImGui::TreePop();
         }
         }
 
 
-        bool opened = ImGui::TreeNode("Tree within single cell");
+        bool node_opened = ImGui::TreeNode("Tree within single cell");
         ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell.");
         ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell.");
-        if (opened)
+        if (node_opened)
         {
         {
             ImGui::Columns(2, "tree items"); 
             ImGui::Columns(2, "tree items"); 
             ImGui::Separator();
             ImGui::Separator();
@@ -2191,16 +2202,15 @@ static void ShowExampleAppPropertyEditor(bool* p_opened)
     ImGui::Columns(2);
     ImGui::Columns(2);
     ImGui::Separator();
     ImGui::Separator();
 
 
-    ImGui::Text("Item1"); ImGui::NextColumn();
-    ImGui::Text("value1"); ImGui::NextColumn();
-
     struct funcs
     struct funcs
     {
     {
         static void ShowDummyObject(const char* prefix, ImU32 uid)
         static void ShowDummyObject(const char* prefix, ImU32 uid)
         {
         {
-            ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
+            ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
+            ImGui::AlignFirstTextHeightToWidgets();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
             bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
             bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
             ImGui::NextColumn();
             ImGui::NextColumn();
+            ImGui::AlignFirstTextHeightToWidgets();
             ImGui::Text("my sailor is rich");
             ImGui::Text("my sailor is rich");
             ImGui::NextColumn();
             ImGui::NextColumn();
             if (opened) 
             if (opened) 

+ 9 - 7
3rdparty/ocornut-imgui/imgui_draw.cpp

@@ -19,7 +19,7 @@
 #include <stdio.h>      // vsnprintf, sscanf, printf
 #include <stdio.h>      // vsnprintf, sscanf, printf
 #include <new>          // new (ptr)
 #include <new>          // new (ptr)
 #if !defined(alloca) && !defined(__FreeBSD__)
 #if !defined(alloca) && !defined(__FreeBSD__)
-#if defined(_WIN32)
+#ifdef _WIN32
 #include <malloc.h>     // alloca
 #include <malloc.h>     // alloca
 #else
 #else
 #include <alloca.h>     // alloca
 #include <alloca.h>     // alloca
@@ -1535,25 +1535,27 @@ const ImWchar*  ImFontAtlas::GetGlyphRangesJapanese()
         19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20,
         19,3,8,0,0,0,4,4,16,0,4,1,5,1,3,0,3,4,6,2,17,10,10,31,6,4,3,6,10,126,7,3,2,2,0,9,0,0,5,20,13,0,15,0,6,0,2,5,8,64,50,3,2,12,2,9,0,0,11,8,20,
         109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
         109,2,18,23,0,0,9,61,3,0,28,41,77,27,19,17,81,5,2,14,5,83,57,252,14,154,263,14,20,8,13,6,57,39,38,
     };
     };
-    static int ranges_unpacked = false;
-    static ImWchar ranges[8 + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1] =
+    static ImWchar base_ranges[] =
     {
     {
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
         0x0020, 0x00FF, // Basic Latin + Latin Supplement
         0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
         0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
         0x31F0, 0x31FF, // Katakana Phonetic Extensions
         0xFF00, 0xFFEF, // Half-width characters
         0xFF00, 0xFFEF, // Half-width characters
     };
     };
-    if (!ranges_unpacked)
+    static bool full_ranges_unpacked = false;
+    static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00)*2 + 1];
+    if (!full_ranges_unpacked)
     {
     {
         // Unpack
         // Unpack
         int codepoint = 0x4e00;
         int codepoint = 0x4e00;
-        ImWchar* dst = &ranges[8];
+        memcpy(full_ranges, base_ranges, sizeof(base_ranges));
+        ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);;
         for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
         for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
             dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
             dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
         dst[0] = 0;
         dst[0] = 0;
-        ranges_unpacked = true;
+        full_ranges_unpacked = true;
     }
     }
-    return &ranges[0];
+    return &full_ranges[0];
 }
 }
 
 
 const ImWchar*  ImFontAtlas::GetGlyphRangesCyrillic()
 const ImWchar*  ImFontAtlas::GetGlyphRangesCyrillic()

+ 56 - 54
3rdparty/ocornut-imgui/imgui_internal.h

@@ -196,33 +196,33 @@ enum ImGuiDataType
 // NB: we can't rely on ImVec2 math operators being available here
 // NB: we can't rely on ImVec2 math operators being available here
 struct IMGUI_API ImRect
 struct IMGUI_API ImRect
 {
 {
-    ImVec2          Min;    // Upper-left
-    ImVec2          Max;    // Lower-right
+    ImVec2      Min;    // Upper-left
+    ImVec2      Max;    // Lower-right
 
 
     ImRect()                                        : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX)  {}
     ImRect()                                        : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX)  {}
     ImRect(const ImVec2& min, const ImVec2& max)    : Min(min), Max(max)                            {}
     ImRect(const ImVec2& min, const ImVec2& max)    : Min(min), Max(max)                            {}
     ImRect(const ImVec4& v)                         : Min(v.x, v.y), Max(v.z, v.w)                  {}
     ImRect(const ImVec4& v)                         : Min(v.x, v.y), Max(v.z, v.w)                  {}
     ImRect(float x1, float y1, float x2, float y2)  : Min(x1, y1), Max(x2, y2)                      {}
     ImRect(float x1, float y1, float x2, float y2)  : Min(x1, y1), Max(x2, y2)                      {}
 
 
-    ImVec2          GetCenter() const               { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
-    ImVec2          GetSize() const                 { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
-    float           GetWidth() const                { return Max.x-Min.x; }
-    float           GetHeight() const               { return Max.y-Min.y; }
-    ImVec2          GetTL() const                   { return Min; }
-    ImVec2          GetTR() const                   { return ImVec2(Max.x, Min.y); }
-    ImVec2          GetBL() const                   { return ImVec2(Min.x, Max.y); }
-    ImVec2          GetBR() const                   { return Max; }
-    bool            Contains(const ImVec2& p) const { return p.x >= Min.x     && p.y >= Min.y     && p.x < Max.x     && p.y < Max.y; }
-    bool            Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
-    bool            Overlaps(const ImRect& r) const { return r.Min.y < Max.y  && r.Max.y > Min.y  && r.Min.x < Max.x && r.Max.x > Min.x; }
-    void            Add(const ImVec2& rhs)          { if (Min.x > rhs.x)     Min.x = rhs.x;     if (Min.y > rhs.y) Min.y = rhs.y;         if (Max.x < rhs.x) Max.x = rhs.x;         if (Max.y < rhs.y) Max.y = rhs.y; }
-    void            Add(const ImRect& rhs)          { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
-    void            Expand(const float amount)      { Min.x -= amount;   Min.y -= amount;   Max.x += amount;   Max.y += amount; }
-    void            Expand(const ImVec2& amount)    { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
-    void            Reduce(const ImVec2& amount)    { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
-    void            Clip(const ImRect& clip)        { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
-    void            Round()                         { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
-    ImVec2          GetClosestPoint(ImVec2 p, bool on_edge) const
+    ImVec2      GetCenter() const               { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
+    ImVec2      GetSize() const                 { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
+    float       GetWidth() const                { return Max.x-Min.x; }
+    float       GetHeight() const               { return Max.y-Min.y; }
+    ImVec2      GetTL() const                   { return Min; }                   // Top-left
+    ImVec2      GetTR() const                   { return ImVec2(Max.x, Min.y); }  // Top-right
+    ImVec2      GetBL() const                   { return ImVec2(Min.x, Max.y); }  // Bottom-left
+    ImVec2      GetBR() const                   { return Max; }                   // Bottom-right
+    bool        Contains(const ImVec2& p) const { return p.x >= Min.x     && p.y >= Min.y     && p.x < Max.x     && p.y < Max.y; }
+    bool        Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
+    bool        Overlaps(const ImRect& r) const { return r.Min.y < Max.y  && r.Max.y > Min.y  && r.Min.x < Max.x && r.Max.x > Min.x; }
+    void        Add(const ImVec2& rhs)          { if (Min.x > rhs.x)     Min.x = rhs.x;     if (Min.y > rhs.y) Min.y = rhs.y;         if (Max.x < rhs.x) Max.x = rhs.x;         if (Max.y < rhs.y) Max.y = rhs.y; }
+    void        Add(const ImRect& rhs)          { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
+    void        Expand(const float amount)      { Min.x -= amount;   Min.y -= amount;   Max.x += amount;   Max.y += amount; }
+    void        Expand(const ImVec2& amount)    { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
+    void        Reduce(const ImVec2& amount)    { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; }
+    void        Clip(const ImRect& clip)        { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
+    void        Round()                         { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
+    ImVec2      GetClosestPoint(ImVec2 p, bool on_edge) const
     {
     {
         if (!on_edge && Contains(p))
         if (!on_edge && Contains(p))
             return p;
             return p;
@@ -237,8 +237,8 @@ struct IMGUI_API ImRect
 // Stacked color modifier, backup of modified data so we can restore it
 // Stacked color modifier, backup of modified data so we can restore it
 struct ImGuiColMod
 struct ImGuiColMod
 {
 {
-    ImGuiCol        Col;
-    ImVec4          PreviousValue;
+    ImGuiCol    Col;
+    ImVec4      PreviousValue;
 };
 };
 
 
 // Stacked style modifier, backup of modified data so we can restore it
 // Stacked style modifier, backup of modified data so we can restore it
@@ -251,34 +251,34 @@ struct ImGuiStyleMod
 // Stacked data for BeginGroup()/EndGroup()
 // Stacked data for BeginGroup()/EndGroup()
 struct ImGuiGroupData
 struct ImGuiGroupData
 {
 {
-    ImVec2          BackupCursorPos;
-    ImVec2          BackupCursorMaxPos;
-    float           BackupIndentX;
-    float           BackupCurrentLineHeight;
-    float           BackupCurrentLineTextBaseOffset;
-    float           BackupLogLinePosY;
-    bool            AdvanceCursor;
+    ImVec2      BackupCursorPos;
+    ImVec2      BackupCursorMaxPos;
+    float       BackupIndentX;
+    float       BackupCurrentLineHeight;
+    float       BackupCurrentLineTextBaseOffset;
+    float       BackupLogLinePosY;
+    bool        AdvanceCursor;
 };
 };
 
 
 // Per column data for Columns()
 // Per column data for Columns()
 struct ImGuiColumnData
 struct ImGuiColumnData
 {
 {
-    float           OffsetNorm;     // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
-    //float         IndentX;
+    float       OffsetNorm;     // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
+    //float     IndentX;
 };
 };
 
 
 // Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and NOT a generic helper.
 // Simple column measurement currently used for MenuItem() only. This is very short-sighted for now and NOT a generic helper.
 struct IMGUI_API ImGuiSimpleColumns
 struct IMGUI_API ImGuiSimpleColumns
 {
 {
-    int                 Count;
-    float               Spacing;
-    float               Width, NextWidth;
-    float               Pos[8], NextWidths[8];
+    int         Count;
+    float       Spacing;
+    float       Width, NextWidth;
+    float       Pos[8], NextWidths[8];
 
 
     ImGuiSimpleColumns();
     ImGuiSimpleColumns();
-    void                Update(int count, float spacing, bool clear);
-    float               DeclColumns(float w0, float w1, float w2);
-    float               CalcExtraSpace(float avail_w);
+    void       Update(int count, float spacing, bool clear);
+    float      DeclColumns(float w0, float w1, float w2);
+    float      CalcExtraSpace(float avail_w);
 };
 };
 
 
 // Internal state of the currently focused/edited text input box
 // Internal state of the currently focused/edited text input box
@@ -294,7 +294,6 @@ struct IMGUI_API ImGuiTextEditState
     ImGuiStb::STB_TexteditState   StbState;
     ImGuiStb::STB_TexteditState   StbState;
     float               CursorAnim;
     float               CursorAnim;
     bool                CursorFollow;
     bool                CursorFollow;
-    ImVec2              InputCursorScreenPos;       // Cursor position in screen space to be used by IME callback.
     bool                SelectedAllMouseLock;
     bool                SelectedAllMouseLock;
 
 
     ImGuiTextEditState()                            { memset(this, 0, sizeof(*this)); }
     ImGuiTextEditState()                            { memset(this, 0, sizeof(*this)); }
@@ -309,11 +308,11 @@ struct IMGUI_API ImGuiTextEditState
 // Data saved in imgui.ini file
 // Data saved in imgui.ini file
 struct ImGuiIniData
 struct ImGuiIniData
 {
 {
-    char*               Name;
-    ImGuiID             ID;
-    ImVec2              Pos;
-    ImVec2              Size;
-    bool                Collapsed;
+    char*       Name;
+    ImGuiID     ID;
+    ImVec2      Pos;
+    ImVec2      Size;
+    bool        Collapsed;
 };
 };
 
 
 // Mouse cursor data (used when io.MouseDrawCursor is set)
 // Mouse cursor data (used when io.MouseDrawCursor is set)
@@ -329,11 +328,11 @@ struct ImGuiMouseCursorData
 // Storage for current popup stack
 // Storage for current popup stack
 struct ImGuiPopupRef
 struct ImGuiPopupRef
 {
 {
-    ImGuiID             PopupID;        // Set on OpenPopup()
-    ImGuiWindow*        Window;         // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
-    ImGuiWindow*        ParentWindow;   // Set on OpenPopup()
-    ImGuiID             ParentMenuSet;  // Set on OpenPopup()
-    ImVec2              MousePosOnOpen; // Copy of mouse position at the time of opening popup
+    ImGuiID         PopupID;        // Set on OpenPopup()
+    ImGuiWindow*    Window;         // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
+    ImGuiWindow*    ParentWindow;   // Set on OpenPopup()
+    ImGuiID         ParentMenuSet;  // Set on OpenPopup()
+    ImVec2          MousePosOnOpen; // Copy of mouse position at the time of opening popup
 
 
     ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
     ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
 };
 };
@@ -361,13 +360,13 @@ struct ImGuiState
     ImGuiWindow*            HoveredWindow;                      // Will catch mouse inputs
     ImGuiWindow*            HoveredWindow;                      // Will catch mouse inputs
     ImGuiWindow*            HoveredRootWindow;                  // Will catch mouse inputs (for focus/move only)
     ImGuiWindow*            HoveredRootWindow;                  // Will catch mouse inputs (for focus/move only)
     ImGuiID                 HoveredId;                          // Hovered widget
     ImGuiID                 HoveredId;                          // Hovered widget
-    bool                    HoveredIdAllowHoveringOthers;
+    bool                    HoveredIdAllowOverlap;
     ImGuiID                 HoveredIdPreviousFrame;
     ImGuiID                 HoveredIdPreviousFrame;
     ImGuiID                 ActiveId;                           // Active widget
     ImGuiID                 ActiveId;                           // Active widget
     ImGuiID                 ActiveIdPreviousFrame;
     ImGuiID                 ActiveIdPreviousFrame;
     bool                    ActiveIdIsAlive;
     bool                    ActiveIdIsAlive;
     bool                    ActiveIdIsJustActivated;            // Set at the time of activation for one frame
     bool                    ActiveIdIsJustActivated;            // Set at the time of activation for one frame
-    bool                    ActiveIdAllowHoveringOthers;        // Set only by active widget
+    bool                    ActiveIdAllowOverlap;               // Set only by active widget
     ImGuiWindow*            ActiveIdWindow;
     ImGuiWindow*            ActiveIdWindow;
     ImGuiWindow*            MovedWindow;                        // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
     ImGuiWindow*            MovedWindow;                        // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
     ImVector<ImGuiIniData>  Settings;                           // .ini Settings
     ImVector<ImGuiIniData>  Settings;                           // .ini Settings
@@ -414,6 +413,7 @@ struct ImGuiState
     ImVec2                  ScrollbarClickDeltaToGrabCenter;   // Distance between mouse and center of grab box, normalized in parent space. Use storage?
     ImVec2                  ScrollbarClickDeltaToGrabCenter;   // Distance between mouse and center of grab box, normalized in parent space. Use storage?
     char                    Tooltip[1024];
     char                    Tooltip[1024];
     char*                   PrivateClipboard;                   // If no custom clipboard handler is defined
     char*                   PrivateClipboard;                   // If no custom clipboard handler is defined
+    ImVec2                  OsImePosRequest, OsImePosSet;       // Cursor position request & last passed to the OS Input Method Editor
 
 
     // Logging
     // Logging
     bool                    LogEnabled;
     bool                    LogEnabled;
@@ -445,13 +445,13 @@ struct ImGuiState
         HoveredWindow = NULL;
         HoveredWindow = NULL;
         HoveredRootWindow = NULL;
         HoveredRootWindow = NULL;
         HoveredId = 0;
         HoveredId = 0;
-        HoveredIdAllowHoveringOthers = false;
+        HoveredIdAllowOverlap = false;
         HoveredIdPreviousFrame = 0;
         HoveredIdPreviousFrame = 0;
         ActiveId = 0;
         ActiveId = 0;
         ActiveIdPreviousFrame = 0;
         ActiveIdPreviousFrame = 0;
         ActiveIdIsAlive = false;
         ActiveIdIsAlive = false;
         ActiveIdIsJustActivated = false;
         ActiveIdIsJustActivated = false;
-        ActiveIdAllowHoveringOthers = false;
+        ActiveIdAllowOverlap = false;
         ActiveIdWindow = NULL;
         ActiveIdWindow = NULL;
         MovedWindow = NULL;
         MovedWindow = NULL;
         SettingsDirtyTimer = 0.0f;
         SettingsDirtyTimer = 0.0f;
@@ -477,6 +477,7 @@ struct ImGuiState
         ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
         ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
         memset(Tooltip, 0, sizeof(Tooltip));
         memset(Tooltip, 0, sizeof(Tooltip));
         PrivateClipboard = NULL;
         PrivateClipboard = NULL;
+        OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
 
 
         ModalWindowDarkeningRatio = 0.0f;
         ModalWindowDarkeningRatio = 0.0f;
         OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
         OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
@@ -682,6 +683,7 @@ namespace ImGui
     IMGUI_API void          FocusableItemUnregister(ImGuiWindow* window);
     IMGUI_API void          FocusableItemUnregister(ImGuiWindow* window);
     IMGUI_API ImVec2        CalcItemSize(ImVec2 size, float default_x, float default_y);
     IMGUI_API ImVec2        CalcItemSize(ImVec2 size, float default_x, float default_y);
     IMGUI_API float         CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
     IMGUI_API float         CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
+    IMGUI_API void          SetItemAllowOverlap();      // Allow last item to be overlapped by a subsequent item
 
 
     // NB: All position are in absolute pixels coordinates (not window coordinates)
     // NB: All position are in absolute pixels coordinates (not window coordinates)
     IMGUI_API void          RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
     IMGUI_API void          RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);