Browse Source

Merge remote-tracking branch 'origin' into 2015-04-indexed-rendering

ocornut 10 years ago
parent
commit
f00662a5ad

+ 4 - 1
examples/directx11_example/imgui_impl_dx11.cpp

@@ -413,7 +413,7 @@ bool    ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex
     io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
     io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
     io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
     io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
     io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
     io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
-    io.KeyMap[ImGuiKey_DownArrow] = VK_UP;
+    io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
     io.KeyMap[ImGuiKey_Home] = VK_HOME;
     io.KeyMap[ImGuiKey_Home] = VK_HOME;
     io.KeyMap[ImGuiKey_End] = VK_END;
     io.KeyMap[ImGuiKey_End] = VK_END;
     io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
     io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
@@ -469,6 +469,9 @@ void ImGui_ImplDX11_NewFrame()
     // io.MouseDown : filled by WM_*BUTTON* events
     // io.MouseDown : filled by WM_*BUTTON* events
     // io.MouseWheel : filled by WM_MOUSEWHEEL events
     // io.MouseWheel : filled by WM_MOUSEWHEEL events
 
 
+    // Hide OS mouse cursor if ImGui is drawing it
+    SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
+
     // Start the frame
     // Start the frame
     ImGui::NewFrame();
     ImGui::NewFrame();
 }
 }

+ 4 - 1
examples/directx9_example/imgui_impl_dx9.cpp

@@ -183,7 +183,7 @@ bool    ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device)
     io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
     io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
     io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
     io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
     io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
     io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
-    io.KeyMap[ImGuiKey_DownArrow] = VK_UP;
+    io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
     io.KeyMap[ImGuiKey_Home] = VK_HOME;
     io.KeyMap[ImGuiKey_Home] = VK_HOME;
     io.KeyMap[ImGuiKey_End] = VK_END;
     io.KeyMap[ImGuiKey_End] = VK_END;
     io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
     io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
@@ -304,6 +304,9 @@ void ImGui_ImplDX9_NewFrame()
     // io.MouseDown : filled by WM_*BUTTON* events
     // io.MouseDown : filled by WM_*BUTTON* events
     // io.MouseWheel : filled by WM_MOUSEWHEEL events
     // io.MouseWheel : filled by WM_MOUSEWHEEL events
 
 
+    // Hide OS mouse cursor if ImGui is drawing it
+    SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
+
     // Start the frame
     // Start the frame
     ImGui::NewFrame();
     ImGui::NewFrame();
 }
 }

+ 1 - 1
examples/opengl3_example/imgui_impl_glfw_gl3.cpp

@@ -355,7 +355,7 @@ void ImGui_ImplGlfwGL3_NewFrame()
     io.MouseWheel = g_MouseWheel;
     io.MouseWheel = g_MouseWheel;
     g_MouseWheel = 0.0f;
     g_MouseWheel = 0.0f;
 
 
-    // Hide/show hardware mouse cursor
+    // Hide OS mouse cursor if ImGui is drawing it
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
 
 
     // Start the frame
     // Start the frame

+ 1 - 1
examples/opengl_example/imgui_impl_glfw.cpp

@@ -259,7 +259,7 @@ void ImGui_ImplGlfw_NewFrame()
     io.MouseWheel = g_MouseWheel;
     io.MouseWheel = g_MouseWheel;
     g_MouseWheel = 0.0f;
     g_MouseWheel = 0.0f;
 
 
-    // Hide/show hardware mouse cursor
+    // Hide OS mouse cursor if ImGui is drawing it
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
 
 
     // Start the frame
     // Start the frame

+ 374 - 181
imgui.cpp

@@ -1,4 +1,4 @@
-// ImGui library v1.38
+// ImGui library v1.39 WIP
 // See ImGui::ShowTestWindow() for sample code.
 // See ImGui::ShowTestWindow() for sample code.
 // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
 // 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
@@ -344,6 +344,7 @@
  - popup: border options. richer api like BeginChild() perhaps? (github issue #197)
  - popup: border options. richer api like BeginChild() perhaps? (github issue #197)
  - combo: turn child handling code into pop up helper
  - combo: turn child handling code into pop up helper
  - 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 keybord for custom listbox (see github pr #203)
  - listbox: multiple selection
  - listbox: multiple selection
  - listbox: user may want to initial scroll to focus on the one selected value?
  - listbox: user may want to initial scroll to focus on the one selected value?
  ! menubar, menus (github issue #126)
  ! menubar, menus (github issue #126)
@@ -380,7 +381,6 @@
  - keyboard: full keyboard navigation and focus.
  - keyboard: full keyboard navigation and focus.
  - input: rework IO to be able to pass actual events to fix temporal aliasing issues.
  - input: rework IO to be able to pass actual events to fix temporal aliasing issues.
  - input: support track pad style scrolling & slider edit.
  - input: support track pad style scrolling & slider edit.
- - tooltip: move to fit within screen (e.g. when mouse cursor is right of the screen).
  - portability: big-endian test/support (github issue #81)
  - portability: big-endian test/support (github issue #81)
  - misc: mark printf compiler attributes on relevant functions
  - misc: mark printf compiler attributes on relevant functions
  - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
  - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL)
@@ -400,9 +400,13 @@
 #include "imgui.h"
 #include "imgui.h"
 #include <ctype.h>      // toupper, isprint
 #include <ctype.h>      // toupper, isprint
 #include <math.h>       // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf
 #include <math.h>       // sqrtf, fabsf, fmodf, powf, cosf, sinf, floorf, ceilf
-#include <stdint.h>     // intptr_t
 #include <stdio.h>      // vsnprintf, sscanf
 #include <stdio.h>      // vsnprintf, sscanf
 #include <new>          // new (ptr)
 #include <new>          // new (ptr)
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h>     // intptr_t
+#else
+#include <stdint.h>     // intptr_t
+#endif
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
 #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
@@ -565,7 +569,8 @@ ImGuiStyle::ImGuiStyle()
     ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
     ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
     ScrollbarWidth          = 16.0f;            // Width of the vertical scrollbar
     ScrollbarWidth          = 16.0f;            // Width of the vertical scrollbar
     GrabMinSize             = 10.0f;            // Minimum width/height of a slider or scrollbar grab
     GrabMinSize             = 10.0f;            // Minimum width/height of a slider or scrollbar grab
-    DisplaySafeAreaPadding  = ImVec2(22,22);    // Window positions are clamped to be visible within the display area. If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding
+    DisplayWindowPadding    = ImVec2(22,22);    // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
+    DisplaySafeAreaPadding  = ImVec2(4,4);      // 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.
 
 
     Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
     Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
     Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
     Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
@@ -958,6 +963,7 @@ struct ImRect           // 2D axis aligned bounding-box
     void        Add(const ImRect& rhs)              { Min.x = ImMin(Min.x, rhs.Min.x); Min.y = ImMin(Min.y, rhs.Min.y); Max.x = ImMax(Max.x, rhs.Max.x); Max.y = ImMax(Max.y, rhs.Max.y); }
     void        Add(const ImRect& rhs)              { Min.x = ImMin(Min.x, rhs.Min.x); Min.y = ImMin(Min.y, rhs.Min.y); Max.x = ImMax(Max.x, rhs.Max.x); Max.y = ImMax(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 float amount)          { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
     void        Expand(const ImVec2& amount)        { Min -= amount; Max += amount; }
     void        Expand(const ImVec2& amount)        { Min -= amount; Max += amount; }
+    void        Reduce(const ImVec2& amount)        { Min += amount; Max -= amount; }
     void        Clip(const ImRect& clip)            { Min.x = ImMax(Min.x, clip.Min.x); Min.y = ImMax(Min.y, clip.Min.y); Max.x = ImMin(Max.x, clip.Max.x); Max.y = ImMin(Max.y, clip.Max.y); }
     void        Clip(const ImRect& clip)            { Min.x = ImMax(Min.x, clip.Min.x); Min.y = ImMax(Min.y, clip.Min.y); Max.x = ImMin(Max.x, clip.Max.x); Max.y = ImMin(Max.y, clip.Max.y); }
     ImVec2      GetClosestPoint(ImVec2 p, bool on_edge) const
     ImVec2      GetClosestPoint(ImVec2 p, bool on_edge) const
     {
     {
@@ -1256,13 +1262,15 @@ struct ImGuiWindow
     float                   ScrollY;
     float                   ScrollY;
     float                   NextScrollY;
     float                   NextScrollY;
     bool                    ScrollbarY;
     bool                    ScrollbarY;
-    bool                    Visible;                            // Set to true on Begin()
-    bool                    WasVisible;
+    bool                    Active;                             // Set to true on Begin()
+    bool                    WasActive;
     bool                    Accessed;                           // Set to true when any widget access the current window
     bool                    Accessed;                           // Set to true when any widget access the current window
     bool                    Collapsed;                          // Set when collapsing window to become only title-bar
     bool                    Collapsed;                          // Set when collapsing window to become only title-bar
     bool                    SkipItems;                          // == Visible && !Collapsed
     bool                    SkipItems;                          // == Visible && !Collapsed
     int                     AutoFitFrames;
     int                     AutoFitFrames;
     bool                    AutoFitOnlyGrows;
     bool                    AutoFitOnlyGrows;
+    int                     AutoPosLastDirection;
+    int                     HiddenFrames;
     int                     SetWindowPosAllowFlags;             // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. 
     int                     SetWindowPosAllowFlags;             // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. 
     int                     SetWindowSizeAllowFlags;            // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. 
     int                     SetWindowSizeAllowFlags;            // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. 
     int                     SetWindowCollapsedAllowFlags;       // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. 
     int                     SetWindowCollapsedAllowFlags;       // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. 
@@ -1415,6 +1423,14 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
     return &it->val_f;
     return &it->val_f;
 }
 }
 
 
+void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
+{
+    ImVector<Pair>::iterator it = LowerBound(Data, key);
+    if (it == Data.end() || it->key != key)
+        it = Data.insert(it, Pair(key, default_val));
+    return &it->val_p;
+}
+
 // FIXME-OPT: Wasting CPU because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
 // FIXME-OPT: Wasting CPU because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
 // However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed.
 // However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed.
 void ImGuiStorage::SetInt(ImU32 key, int val)
 void ImGuiStorage::SetInt(ImU32 key, int val)
@@ -1606,12 +1622,14 @@ ImGuiWindow::ImGuiWindow(const char* name)
     ScrollY = 0.0f;
     ScrollY = 0.0f;
     NextScrollY = 0.0f;
     NextScrollY = 0.0f;
     ScrollbarY = false;
     ScrollbarY = false;
-    Visible = WasVisible = false;
+    Active = WasActive = false;
     Accessed = false;
     Accessed = false;
     Collapsed = false;
     Collapsed = false;
     SkipItems = false;
     SkipItems = false;
     AutoFitFrames = -1;
     AutoFitFrames = -1;
     AutoFitOnlyGrows = false;
     AutoFitOnlyGrows = false;
+    AutoPosLastDirection = -1;
+    HiddenFrames = 0;
     SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver;
     SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver;
 
 
     LastFrameDrawn = -1;
     LastFrameDrawn = -1;
@@ -1704,7 +1722,7 @@ static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiW
     for (size_t i = 0; i < window->DC.ChildWindows.size(); i++)
     for (size_t i = 0; i < window->DC.ChildWindows.size(); i++)
     {
     {
         ImGuiWindow* child = window->DC.ChildWindows[i];
         ImGuiWindow* child = window->DC.ChildWindows[i];
-        if (child->Visible)                 // clipped children may have been marked not Visible
+        if (child->Active)                 // clipped children may have been marked not active
             AddWindowToRenderList(out_render_list, child);
             AddWindowToRenderList(out_render_list, child);
     }
     }
 }
 }
@@ -2028,7 +2046,7 @@ void ImGui::NewFrame()
 
 
     // Pressing TAB activate widget focus
     // Pressing TAB activate widget focus
     // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.
     // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.
-    if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Visible && IsKeyPressedMap(ImGuiKey_Tab, false))
+    if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false))
     {
     {
         g.FocusedWindow->FocusIdxTabRequestNext = 0;
         g.FocusedWindow->FocusIdxTabRequestNext = 0;
     }
     }
@@ -2037,8 +2055,8 @@ void ImGui::NewFrame()
     for (size_t i = 0; i != g.Windows.size(); i++)
     for (size_t i = 0; i != g.Windows.size(); i++)
     {
     {
         ImGuiWindow* window = g.Windows[i];
         ImGuiWindow* window = g.Windows[i];
-        window->WasVisible = window->Visible;
-        window->Visible = false;
+        window->WasActive = window->Active;
+        window->Active = false;
         window->Accessed = false;
         window->Accessed = false;
     }
     }
 
 
@@ -2123,7 +2141,7 @@ static int ChildWindowComparer(const void* lhs, const void* rhs)
 static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window)
 static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window)
 {
 {
     out_sorted_windows.push_back(window);
     out_sorted_windows.push_back(window);
-    if (window->Visible)
+    if (window->Active)
     {
     {
         const size_t count = window->DC.ChildWindows.size();
         const size_t count = window->DC.ChildWindows.size();
         if (count > 1)
         if (count > 1)
@@ -2131,7 +2149,7 @@ static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows,
         for (size_t i = 0; i < count; i++)
         for (size_t i = 0; i < count; i++)
         {
         {
             ImGuiWindow* child = window->DC.ChildWindows[i];
             ImGuiWindow* child = window->DC.ChildWindows[i];
-            if (child->Visible)
+            if (child->Active)
                 AddWindowToSortedBuffer(out_sorted_windows, child);
                 AddWindowToSortedBuffer(out_sorted_windows, child);
         }
         }
     }
     }
@@ -2176,7 +2194,7 @@ void ImGui::Render()
         // Hide implicit window if it hasn't been used
         // Hide implicit 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 
         if (g.CurrentWindow && !g.CurrentWindow->Accessed)
         if (g.CurrentWindow && !g.CurrentWindow->Accessed)
-            g.CurrentWindow->Visible = false;
+            g.CurrentWindow->Active = false;
         ImGui::End();
         ImGui::End();
 
 
         if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
         if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
@@ -2202,12 +2220,12 @@ void ImGui::Render()
         for (size_t i = 0; i != g.Windows.size(); i++)
         for (size_t 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 visible its parent will add it
-                if (window->Visible)
+            if (window->Flags & ImGuiWindowFlags_ChildWindow)       // if a child is active its parent will add it
+                if (window->Active)
                     continue;
                     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
         g.Windows.swap(g.WindowsSortBuffer);
         g.Windows.swap(g.WindowsSortBuffer);
 
 
         // Clear data for next frame
         // Clear data for next frame
@@ -2235,7 +2253,7 @@ void ImGui::Render()
         for (size_t i = 0; i != g.Windows.size(); i++)
         for (size_t i = 0; i != g.Windows.size(); i++)
         {
         {
             ImGuiWindow* window = g.Windows[i];
             ImGuiWindow* window = g.Windows[i];
-            if (window->Visible && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0)
+            if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0)
             {
             {
                 // FIXME: Generalize this with a proper layering system so we can stack.
                 // FIXME: Generalize this with a proper layering system so we can stack.
                 if (window->Flags & ImGuiWindowFlags_Popup)
                 if (window->Flags & ImGuiWindowFlags_Popup)
@@ -2582,7 +2600,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)
     for (int i = (int)g.Windows.size()-1; i >= 0; i--)
     for (int i = (int)g.Windows.size()-1; i >= 0; i--)
     {
     {
         ImGuiWindow* window = g.Windows[(size_t)i];
         ImGuiWindow* window = g.Windows[(size_t)i];
-        if (!window->Visible)
+        if (!window->Active)
             continue;
             continue;
         if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
         if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
             continue;
             continue;
@@ -2646,6 +2664,13 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
     return ImGui::IsKeyPressed(key_index, repeat);
     return ImGui::IsKeyPressed(key_index, repeat);
 }
 }
 
 
+bool ImGui::IsKeyDown(int key_index)
+{
+    ImGuiState& g = *GImGui;
+    IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+    return g.IO.KeysDown[key_index];
+}
+
 bool ImGui::IsKeyPressed(int key_index, bool repeat)
 bool ImGui::IsKeyPressed(int key_index, bool repeat)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
@@ -2664,6 +2689,13 @@ bool ImGui::IsKeyPressed(int key_index, bool repeat)
     return false;
     return false;
 }
 }
 
 
+bool ImGui::IsMouseDown(int button)
+{
+    ImGuiState& g = *GImGui;
+    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+    return g.IO.MouseDown[button];
+}
+
 bool ImGui::IsMouseClicked(int button, bool repeat)
 bool ImGui::IsMouseClicked(int button, bool repeat)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
@@ -2820,6 +2852,14 @@ int ImGui::GetFrameCount()
     return GImGui->FrameCount;
     return GImGui->FrameCount;
 }
 }
 
 
+static ImVec4 GetVisibleRect()
+{
+    ImGuiState& g = *GImGui;
+    if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
+        return ImVec4(g.IO.DisplayVisibleMin.x, g.IO.DisplayVisibleMin.y, g.IO.DisplayVisibleMax.x, g.IO.DisplayVisibleMax.y);
+    return ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
+}
+
 void ImGui::BeginTooltip()
 void ImGui::BeginTooltip()
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
@@ -2940,6 +2980,30 @@ void ImGui::EndChildFrame()
     ImGui::PopStyleColor();
     ImGui::PopStyleColor();
 }
 }
 
 
+static ImVec2 FindBestWindowPos(const ImVec2& mouse_pos, const ImVec2& size, int* last_dir, const ImRect& r_inner)
+{
+    const ImGuiStyle& style = GImGui->Style;
+
+    // Clamp into visible area while not overlapping the cursor
+    ImRect r_outer(GetVisibleRect()); 
+    r_outer.Reduce(style.DisplaySafeAreaPadding);
+    ImVec2 mouse_pos_clamped = ImClamp(mouse_pos, r_outer.Min, r_outer.Max - size);
+
+    for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++)   // Right, down, up, left. Favor last used direction.
+    {
+        const int dir = (n == -1) ? *last_dir : n;
+        ImRect rect(dir == 0 ? r_inner.Max.x : r_outer.Min.x, dir == 1 ? r_inner.Max.y : r_outer.Min.y, dir == 3 ? r_inner.Min.x : r_outer.Max.x, dir == 2 ? r_inner.Min.y : r_outer.Max.y);
+        if (rect.GetWidth() < size.x || rect.GetHeight() < size.y)
+            continue;
+        *last_dir = dir;
+        return ImVec2(dir == 0 ? r_inner.Max.x : dir == 3 ? r_inner.Min.x - size.x : mouse_pos_clamped.x, dir == 1 ? r_inner.Max.y : dir == 2 ? r_inner.Min.y - size.y : mouse_pos_clamped.y);
+    }
+
+    // Fallback
+	*last_dir = -1;
+    return mouse_pos + ImVec2(2,2);
+}
+
 static ImGuiWindow* FindWindowByName(const char* name)
 static ImGuiWindow* FindWindowByName(const char* name)
 {
 {
     // FIXME-OPT: Store sorted hashes -> pointers.
     // FIXME-OPT: Store sorted hashes -> pointers.
@@ -3094,67 +3158,148 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
     const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame);
     const bool first_begin_of_the_frame = (window->LastFrameDrawn != current_frame);
     if (first_begin_of_the_frame)
     if (first_begin_of_the_frame)
     {
     {
+        window->Active = true;
         window->DrawList->Clear();
         window->DrawList->Clear();
-        window->Visible = true;
+        window->ClipRectStack.resize(0);
+        window->LastFrameDrawn = current_frame;
+        window->IDStack.resize(1);
+    }
+
+    // Setup texture, outer clipping rectangle
+    window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
+    if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
+        PushClipRect(parent_window->ClipRectStack.back());
+    else
+        PushClipRect(GetVisibleRect());
 
 
+    if (first_begin_of_the_frame)
+    {
         // New windows appears in front
         // New windows appears in front
-        if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
+        if (!window->WasActive)
         {
         {
-            if (window->LastFrameDrawn < current_frame - 1)
+            window->AutoPosLastDirection = -1;
+
+            if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
             {
             {
                 FocusWindow(window);
                 FocusWindow(window);
 
 
-                // Popup position themselves when they first appear
-                if (flags & ImGuiWindowFlags_Popup)
-                {
-                    if (!window_pos_set_by_api)
-                        window->PosFloat = g.IO.MousePos;
-                }
+                // Popup first latch mouse position, will position itself when it appears next frame
+                if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
+                    window->PosFloat = g.IO.MousePos;
             }
             }
         }
         }
 
 
-        window->LastFrameDrawn = current_frame;
-        window->ClipRectStack.resize(0);
+        // Collapse window by double-clicking on title bar
+        // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
+        if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
+        {
+            if (g.HoveredWindow == window && IsMouseHoveringRect(window->TitleBarRect()) && g.IO.MouseDoubleClicked[0])
+            {
+                window->Collapsed = !window->Collapsed;
+                if (!(flags & ImGuiWindowFlags_NoSavedSettings))
+                    MarkSettingsDirty();
+                FocusWindow(window);
+            }
+        }
+        else
+        {
+            window->Collapsed = false;
+        }
+
+        const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1);
+        if (window->HiddenFrames > 0)
+            window->HiddenFrames--;
 
 
-        // Reset contents size for auto-fitting
+        // SIZE
+
+        // Save contents size from last frame for auto-fitting
         window->SizeContents = window_is_new ? ImVec2(0.0f, 0.0f) : window->DC.CursorMaxPos - window->Pos;
         window->SizeContents = window_is_new ? ImVec2(0.0f, 0.0f) : window->DC.CursorMaxPos - window->Pos;
         window->SizeContents.y += window->ScrollY;
         window->SizeContents.y += window->ScrollY;
 
 
+        // Hide popup/tooltip window when first appearing while we measure size (because we recycle them)
+        if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && !window->WasActive)
+        {
+            window->HiddenFrames = 1;
+            window->Size = window->SizeFull = window->SizeContents = ImVec2(0.f, 0.f);  // TODO: We don't support SetNextWindowSize() for tooltips or popups yet
+        }
+
+        // Calculate auto-fit size
+        ImVec2 size_auto_fit;
+        if ((flags & ImGuiWindowFlags_Tooltip) != 0)
+        {
+            // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
+            size_auto_fit = window->SizeContents + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);
+        }
+        else
+        {
+            size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding));
+            if (size_auto_fit.y < window->SizeContents.y + style.AutoFitPadding.y)
+                size_auto_fit.x += style.ScrollbarWidth;
+        }
+
+        // Handle automatic resize
+        if (window->Collapsed)
+        {
+            // We still process initial auto-fit on collapsed windows to get a window width,
+            // But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
+            if (window->AutoFitFrames > 0)
+                window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit;
+            window->Size = window->TitleBarRect().GetSize();
+        }
+        else
+        {
+            if (flags & ImGuiWindowFlags_AlwaysAutoResize)
+            {
+                window->SizeFull = size_auto_fit;
+            }
+            else if (window->AutoFitFrames > 0)
+            {
+                // Auto-fit only grows during the first few frames
+                window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit;
+                if (!(flags & ImGuiWindowFlags_NoSavedSettings))
+                    MarkSettingsDirty();
+            }
+            window->Size = window->SizeFull;
+        }
+
+        // Minimum window size
+        if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
+            window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize);
+
+        // POSITION
+
+        // Position child window
         if (flags & ImGuiWindowFlags_ChildWindow)
         if (flags & ImGuiWindowFlags_ChildWindow)
         {
         {
             parent_window->DC.ChildWindows.push_back(window);
             parent_window->DC.ChildWindows.push_back(window);
             window->Pos = window->PosFloat = parent_window->DC.CursorPos;
             window->Pos = window->PosFloat = parent_window->DC.CursorPos;
-            window->SizeFull = size_on_first_use;
+            window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user.
         }
         }
-    }
-
-    // Setup texture
-    window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
 
 
-    // Setup outer clipping rectangle
-    if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
-        PushClipRect(parent_window->ClipRectStack.back());
-    else if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
-        PushClipRect(ImVec4(g.IO.DisplayVisibleMin.x, g.IO.DisplayVisibleMin.y, g.IO.DisplayVisibleMax.x, g.IO.DisplayVisibleMax.y));
-    else
-        PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
+        // Position popup
+        if ((flags & ImGuiWindowFlags_Popup) != 0 && window_appearing_after_being_hidden && !window_pos_set_by_api)
+        {
+            ImRect rect_to_avoid(window->PosFloat.x - 1, window->PosFloat.y - 1, window->PosFloat.x + 1, window->PosFloat.y + 1);
+            window->PosFloat = FindBestWindowPos(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
+        }
 
 
-    // Setup and draw window
-    if (first_begin_of_the_frame)
-    {
-        // Reset ID stack
-        window->IDStack.resize(1);
+        // Position tooltip (always follows mouse)
+        if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api)
+        {
+            ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, g.IO.MousePos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead?
+            window->PosFloat = FindBestWindowPos(g.IO.MousePos, window->Size, &window->AutoPosLastDirection, rect_to_avoid);
+        }
 
 
-        // Move window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.
+        // User moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.
         RegisterAliveId(window->MoveID);
         RegisterAliveId(window->MoveID);
         if (g.ActiveId == window->MoveID)
         if (g.ActiveId == window->MoveID)
         {
         {
             if (g.IO.MouseDown[0])
             if (g.IO.MouseDown[0])
             {
             {
-                if (!(window->Flags & ImGuiWindowFlags_NoMove))
+                if (!(flags & ImGuiWindowFlags_NoMove))
                 {
                 {
                     window->PosFloat += g.IO.MouseDelta;
                     window->PosFloat += g.IO.MouseDelta;
-                    if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
+                    if (!(flags & ImGuiWindowFlags_NoSavedSettings))
                         MarkSettingsDirty();
                         MarkSettingsDirty();
                 }
                 }
                 IM_ASSERT(g.MovedWindow != NULL);
                 IM_ASSERT(g.MovedWindow != NULL);
@@ -3167,28 +3312,20 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
             }
             }
         }
         }
 
 
-        // Tooltips always follows mouse
-        if (!window_pos_set_by_api && (window->Flags & ImGuiWindowFlags_Tooltip) != 0)
-        {
-            window->PosFloat = g.IO.MousePos + ImVec2(32,16) - style.FramePadding*2;
-        }
-
-        // Clamp into view
-        if (!(window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Tooltip))
+        // Clamp into display
+        if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
         {
         {
             if (window->AutoFitFrames <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
             if (window->AutoFitFrames <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
             {
             {
-                ImVec2 clip_min = style.DisplaySafeAreaPadding;
-                ImVec2 clip_max = g.IO.DisplaySize - style.DisplaySafeAreaPadding;
-                window->PosFloat = ImMax(window->PosFloat + window->Size, clip_min) - window->Size;
-                window->PosFloat = ImMin(window->PosFloat, clip_max);
+                ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
+                window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size;
+                window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding);
             }
             }
-            window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize);
         }
         }
         window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
         window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
 
 
         // Default item width. Make it proportional to window size if window manually resizes
         // Default item width. Make it proportional to window size if window manually resizes
-        if (window->Size.x > 0.0f && !(window->Flags & ImGuiWindowFlags_Tooltip) && !(window->Flags & ImGuiWindowFlags_AlwaysAutoResize))
+        if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
             window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
             window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
         else
         else
             window->ItemWidthDefault = 200.0f;
             window->ItemWidthDefault = 200.0f;
@@ -3205,61 +3342,21 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
         window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
         window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
         window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX;
         window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX;
 
 
-        ImRect title_bar_rect = window->TitleBarRect();
-
-        // Apply and ImClamp scrolling
+        // Apply scrolling
         window->ScrollY = window->NextScrollY;
         window->ScrollY = window->NextScrollY;
         window->ScrollY = ImMax(window->ScrollY, 0.0f);
         window->ScrollY = ImMax(window->ScrollY, 0.0f);
         if (!window->Collapsed && !window->SkipItems)
         if (!window->Collapsed && !window->SkipItems)
             window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, window->SizeContents.y - window->SizeFull.y));
             window->ScrollY = ImMin(window->ScrollY, ImMax(0.0f, window->SizeContents.y - window->SizeFull.y));
         window->NextScrollY = window->ScrollY;
         window->NextScrollY = window->ScrollY;
 
 
-        // At this point we don't have a clipping rectangle setup yet, so we can test and draw in title bar
-        // Collapse window by double-clicking on title bar
-        if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
-        {
-            if (!(window->Flags & ImGuiWindowFlags_NoCollapse) && g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect) && g.IO.MouseDoubleClicked[0])
-            {
-                window->Collapsed = !window->Collapsed;
-                if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
-                    MarkSettingsDirty();
-                FocusWindow(window);
-            }
-        }
-        else
-        {
-            window->Collapsed = false;
-        }
-
-        // Calculate auto-fit size
-        ImVec2 size_auto_fit;
-        if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
-        {
-            // Tooltip always resize. We keep the spacing symmetric on both axises for aesthetic purpose.
-            size_auto_fit = window->SizeContents + style.WindowPadding - ImVec2(0.0f, style.ItemSpacing.y);
-        }
-        else
-        {
-            size_auto_fit = ImClamp(window->SizeContents + style.AutoFitPadding, style.WindowMinSize, ImMax(style.WindowMinSize, g.IO.DisplaySize - style.AutoFitPadding));
-            if (size_auto_fit.y < window->SizeContents.y + style.AutoFitPadding.y)
-                size_auto_fit.x += style.ScrollbarWidth;
-        }
-
-        const float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
+        // Draw window + handle manual resize
+        ImRect title_bar_rect = window->TitleBarRect();
+        const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
         if (window->Collapsed)
         if (window->Collapsed)
         {
         {
-            // We still process initial auto-fit on collapsed windows to get a window width
-            // But otherwise we don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
-            if (window->AutoFitFrames > 0)
-            {
-                window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit;
-                title_bar_rect = window->TitleBarRect();
-            }
-        
             // Draw title bar only
             // Draw title bar only
-            window->Size = title_bar_rect.GetSize();
             window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_TitleBgCollapsed), window_rounding);
             window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_TitleBgCollapsed), window_rounding);
-            if (window->Flags & ImGuiWindowFlags_ShowBorders)
+            if (flags & ImGuiWindowFlags_ShowBorders)
             {
             {
                 window->DrawList->AddRect(title_bar_rect.GetTL()+ImVec2(1,1), title_bar_rect.GetBR()+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
                 window->DrawList->AddRect(title_bar_rect.GetTL()+ImVec2(1,1), title_bar_rect.GetBR()+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
                 window->DrawList->AddRect(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_Border), window_rounding);
                 window->DrawList->AddRect(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_Border), window_rounding);
@@ -3268,84 +3365,63 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
         else
         else
         {
         {
             ImU32 resize_col = 0;
             ImU32 resize_col = 0;
-            if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
-            {
-                window->Size = window->SizeFull = size_auto_fit;
-            }
-            else
+            if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFrames <= 0 && !(flags & ImGuiWindowFlags_NoResize))
             {
             {
-                if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
+                // Manual resize
+                const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR());
+                const ImGuiID resize_id = window->GetID("#RESIZE");
+                bool hovered, held;
+                ButtonBehavior(resize_rect, resize_id, &hovered, &held, true);
+                resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
+
+                if (hovered || held)
+                    g.MouseCursor = ImGuiMouseCursor_ResizeNWSE;
+
+                if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
                 {
                 {
-                    // Don't continuously mark settings as dirty, the size of the window doesn't need to be stored.
+                    // Manual auto-fit when double-clicking
                     window->SizeFull = size_auto_fit;
                     window->SizeFull = size_auto_fit;
-                }
-                else if (window->AutoFitFrames > 0)
-                {
-                    // Auto-fit only grows during the first few frames
-                    window->SizeFull = window->AutoFitOnlyGrows ? ImMax(window->SizeFull, size_auto_fit) : size_auto_fit;
-                    if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
+                    if (!(flags & ImGuiWindowFlags_NoSavedSettings))
                         MarkSettingsDirty();
                         MarkSettingsDirty();
+                    SetActiveId(0);
                 }
                 }
-                else if (!(window->Flags & ImGuiWindowFlags_NoResize))
+                else if (held)
                 {
                 {
-                    // Manual resize grip
-                    const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR());
-                    const ImGuiID resize_id = window->GetID("#RESIZE");
-                    bool hovered, held;
-                    ButtonBehavior(resize_rect, resize_id, &hovered, &held, true);
-                    resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
-
-                    if (hovered || held)
-                        g.MouseCursor = ImGuiMouseCursor_ResizeNWSE;
-
-                    if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
-                    {
-                        // Manual auto-fit when double-clicking
-                        window->SizeFull = size_auto_fit;
-                        if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
-                            MarkSettingsDirty();
-                        SetActiveId(0);
-                    }
-                    else if (held)
-                    {
-                        // Resize
-                        window->SizeFull = ImMax(window->SizeFull + g.IO.MouseDelta, style.WindowMinSize);
-                        if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
-                            MarkSettingsDirty();
-                    }
+                    window->SizeFull = ImMax(window->SizeFull + g.IO.MouseDelta, style.WindowMinSize);
+                    if (!(flags & ImGuiWindowFlags_NoSavedSettings))
+                        MarkSettingsDirty();
                 }
                 }
 
 
-                // Update rectangle immediately so that rendering right below us isn't one frame late
                 window->Size = window->SizeFull;
                 window->Size = window->SizeFull;
                 title_bar_rect = window->TitleBarRect();
                 title_bar_rect = window->TitleBarRect();
             }
             }
 
 
             // Scrollbar
             // Scrollbar
-            window->ScrollbarY = (window->SizeContents.y > window->Size.y) && !(window->Flags & ImGuiWindowFlags_NoScrollbar);
+            window->ScrollbarY = (window->SizeContents.y > window->Size.y) && !(flags & ImGuiWindowFlags_NoScrollbar);
 
 
             // Window background
             // Window background
             if (bg_alpha > 0.0f)
             if (bg_alpha > 0.0f)
             {
             {
-                if ((window->Flags & ImGuiWindowFlags_ComboBox) != 0)
+                if ((flags & ImGuiWindowFlags_ComboBox) != 0)
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_ComboBg, bg_alpha), window_rounding);
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_ComboBg, bg_alpha), window_rounding);
-                else if ((window->Flags & ImGuiWindowFlags_Tooltip) != 0)
+                else if ((flags & ImGuiWindowFlags_Tooltip) != 0)
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_TooltipBg, bg_alpha), window_rounding);
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_TooltipBg, bg_alpha), window_rounding);
-                else if ((window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
+                else if ((flags & ImGuiWindowFlags_ChildWindow) != 0)
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size-ImVec2(window->ScrollbarY?style.ScrollbarWidth:0.0f,0.0f), window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size-ImVec2(window->ScrollbarY?style.ScrollbarWidth:0.0f,0.0f), window->Color(ImGuiCol_ChildWindowBg, bg_alpha), window_rounding, window->ScrollbarY ? (1|8) : (0xF));
                 else
                 else
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
                     window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_WindowBg, bg_alpha), window_rounding);
             }
             }
 
 
             // Title bar
             // Title bar
-            if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
+            if (!(flags & ImGuiWindowFlags_NoTitleBar))
                 window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_TitleBg), window_rounding, 1|2);
                 window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_TitleBg), window_rounding, 1|2);
 
 
             // Borders
             // Borders
-            if (window->Flags & ImGuiWindowFlags_ShowBorders)
+            if (flags & ImGuiWindowFlags_ShowBorders)
             {
             {
                 window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
                 window->DrawList->AddRect(window->Pos+ImVec2(1,1), window->Pos+window->Size+ImVec2(1,1), window->Color(ImGuiCol_BorderShadow), window_rounding);
                 window->DrawList->AddRect(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_Border), window_rounding);
                 window->DrawList->AddRect(window->Pos, window->Pos+window->Size, window->Color(ImGuiCol_Border), window_rounding);
-                if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
+                if (!(flags & ImGuiWindowFlags_NoTitleBar))
                     window->DrawList->AddLine(title_bar_rect.GetBL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_Border));
                     window->DrawList->AddLine(title_bar_rect.GetBL(), title_bar_rect.GetBR(), window->Color(ImGuiCol_Border));
             }
             }
 
 
@@ -3355,7 +3431,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
 
 
             // Render resize grip
             // Render resize grip
             // (after the input handling so we don't have a frame of latency)
             // (after the input handling so we don't have a frame of latency)
-            if (!(window->Flags & ImGuiWindowFlags_NoResize))
+            if (!(flags & ImGuiWindowFlags_NoResize))
             {
             {
                 const float r = window_rounding;
                 const float r = window_rounding;
                 const ImVec2 br = window->Rect().GetBR();
                 const ImVec2 br = window->Rect().GetBR();
@@ -3403,13 +3479,13 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
             window->AutoFitFrames--;
             window->AutoFitFrames--;
 
 
         // Title bar
         // Title bar
-        if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
+        if (!(flags & ImGuiWindowFlags_NoTitleBar))
         {
         {
             if (p_opened != NULL)
             if (p_opened != NULL)
                 CloseWindowButton(p_opened);
                 CloseWindowButton(p_opened);
 
 
             ImVec2 text_min = window->Pos + style.FramePadding;
             ImVec2 text_min = window->Pos + style.FramePadding;
-            if (!(window->Flags & ImGuiWindowFlags_NoCollapse))
+            if (!(flags & ImGuiWindowFlags_NoCollapse))
             {
             {
                 RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
                 RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
                 text_min.x += g.FontSize + style.ItemInnerSpacing.x;
                 text_min.x += g.FontSize + style.ItemInnerSpacing.x;
@@ -3419,7 +3495,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
             const ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? (title_bar_rect.GetHeight()-3) : style.FramePadding.x), style.FramePadding.y*2 + text_size.y);
             const ImVec2 text_max = window->Pos + ImVec2(window->Size.x - (p_opened ? (title_bar_rect.GetHeight()-3) : style.FramePadding.x), style.FramePadding.y*2 + text_size.y);
             RenderTextClipped(text_min, name, NULL, &text_size, text_max);
             RenderTextClipped(text_min, name, NULL, &text_size, text_max);
         }
         }
-        if (window->Flags & ImGuiWindowFlags_Popup)
+        if (flags & ImGuiWindowFlags_Popup)
         {
         {
             if (p_opened)
             if (p_opened)
             {
             {
@@ -3472,13 +3548,13 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
         // We also hide the window from rendering because we've already added its border to the command list.
         // We also hide the window from rendering because we've already added its border to the command list.
         // (we could perform the check earlier in the function but it is simpler at this point)
         // (we could perform the check earlier in the function but it is simpler at this point)
         if (window->Collapsed)
         if (window->Collapsed)
-            window->Visible = false;
+            window->Active = false;
     }
     }
     if (style.Alpha <= 0.0f)
     if (style.Alpha <= 0.0f)
-        window->Visible = false;
+        window->Active = false;
 
 
     // Return false if we don't intend to display anything to allow user to perform an early out optimization
     // Return false if we don't intend to display anything to allow user to perform an early out optimization
-    window->SkipItems = (window->Collapsed || !window->Visible) && window->AutoFitFrames <= 0;
+    window->SkipItems = (window->Collapsed || !window->Active) && window->AutoFitFrames <= 0;
     return !window->SkipItems;
     return !window->SkipItems;
 }
 }
 
 
@@ -4374,7 +4450,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window)
     // An active popup disable hovering on other windows (apart from its own children)
     // An active popup disable hovering on other windows (apart from its own children)
     if (ImGuiWindow* focused_window = g.FocusedWindow)
     if (ImGuiWindow* focused_window = g.FocusedWindow)
         if (ImGuiWindow* focused_root_window = focused_window->RootWindow)
         if (ImGuiWindow* focused_root_window = focused_window->RootWindow)
-            if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasVisible && focused_root_window != window->RootWindow)
+            if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
                 return false;
                 return false;
 
 
     return true;
     return true;
@@ -5417,7 +5493,7 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
 }
 }
 
 
 // Add multiple sliders on 1 line for compact edition of multiple components
 // Add multiple sliders on 1 line for compact edition of multiple components
-static bool SliderFloatN(const char* label, float v[3], int components, float v_min, float v_max, const char* display_format, float power)
+static bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -5469,7 +5545,7 @@ bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max
     return SliderFloatN(label, v, 4, v_min, v_max, display_format, power);
     return SliderFloatN(label, v, 4, v_min, v_max, display_format, power);
 }
 }
 
 
-static bool SliderIntN(const char* label, int v[3], int components, int v_min, int v_max, const char* display_format)
+static bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -5664,6 +5740,58 @@ bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, f
     return value_changed;
     return value_changed;
 }
 }
 
 
+static bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power)
+{
+    ImGuiState& g = *GImGui;
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return false;
+
+    const ImGuiStyle& style = g.Style;
+    const float w_full = ImGui::CalcItemWidth();
+    const float w_item_one  = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
+    const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
+
+    bool value_changed = false;
+    ImGui::BeginGroup();
+    ImGui::PushID(label);
+    ImGui::PushItemWidth(w_item_one);
+    for (int i = 0; i < components; i++)
+    {
+        ImGui::PushID(i);
+        if (i + 1 == components)
+        {
+            ImGui::PopItemWidth();
+            ImGui::PushItemWidth(w_item_last);
+        }
+        value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power);
+        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::PopID();
+    }
+    ImGui::PopItemWidth();
+    ImGui::PopID();
+
+    ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
+    ImGui::EndGroup();
+
+    return value_changed;
+}
+
+bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power)
+{
+    return DragFloatN(label, v, 2, v_speed, v_min, v_max, display_format, power);
+}
+
+bool ImGui::DragFloat3(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power)
+{
+    return DragFloatN(label, v, 3, v_speed, v_min, v_max, display_format, power);
+}
+
+bool ImGui::DragFloat4(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* display_format, float power)
+{
+    return DragFloatN(label, v, 4, v_speed, v_min, v_max, display_format, power);
+}
+
 // NB: v_speed is float to allow adjusting the drag speed with more precision
 // NB: v_speed is float to allow adjusting the drag speed with more precision
 bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format)
 bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format)
 {
 {
@@ -5675,6 +5803,58 @@ bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_m
     return value_changed;
     return value_changed;
 }
 }
 
 
+static bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format)
+{
+    ImGuiState& g = *GImGui;
+    ImGuiWindow* window = GetCurrentWindow();
+    if (window->SkipItems)
+        return false;
+
+    const ImGuiStyle& style = g.Style;
+    const float w_full = ImGui::CalcItemWidth();
+    const float w_item_one  = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)) / (float)components));
+    const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x)*(components-1)));
+
+    bool value_changed = false;
+    ImGui::BeginGroup();
+    ImGui::PushID(label);
+    ImGui::PushItemWidth(w_item_one);
+    for (int i = 0; i < components; i++)
+    {
+        ImGui::PushID(i);
+        if (i + 1 == components)
+        {
+            ImGui::PopItemWidth();
+            ImGui::PushItemWidth(w_item_last);
+        }
+        value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format);
+        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::PopID();
+    }
+    ImGui::PopItemWidth();
+    ImGui::PopID();
+
+    ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
+    ImGui::EndGroup();
+
+    return value_changed;
+}
+
+bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* display_format)
+{
+    return DragIntN(label, v, 2, v_speed, v_min, v_max, display_format);
+}
+
+bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* display_format)
+{
+    return DragIntN(label, v, 3, v_speed, v_min, v_max, display_format);
+}
+
+bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* display_format)
+{
+    return DragIntN(label, v, 4, v_speed, v_min, v_max, display_format);
+}
+
 enum ImGuiPlotType
 enum ImGuiPlotType
 {
 {
     ImGuiPlotType_Lines,
     ImGuiPlotType_Lines,
@@ -6540,7 +6720,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
                     if (callback_data.SelectionEnd != utf8_selection_end)      edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);
                     if (callback_data.SelectionEnd != utf8_selection_end)      edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd);
                     if (callback_data.BufDirty)
                     if (callback_data.BufDirty)
                     {
                     {
-                        ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), g.TempBuffer, NULL);
+                        edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), g.TempBuffer, NULL);
+                        edit_state.CurLenA = strlen(g.TempBuffer);
                         edit_state.CursorAnimReset();
                         edit_state.CursorAnimReset();
                     }
                     }
                 }
                 }
@@ -6877,7 +7058,8 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg)
     const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : w, size_arg.y != 0.0f ? size_arg.y : label_size.y);
     const ImVec2 size(size_arg.x != 0.0f ? size_arg.x : w, size_arg.y != 0.0f ? size_arg.y : label_size.y);
     ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
     ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
     ItemSize(bb);
     ItemSize(bb);
-    bb.Max.x += style.AutoFitPadding.x;
+    if (size_arg.x == 0.0f)
+        bb.Max.x += style.AutoFitPadding.x;
 
 
     // Selectables are meant to be tightly packed together. So for both rendering and collision we extend to compensate for spacing.
     // Selectables are meant to be tightly packed together. So for both rendering and collision we extend to compensate for spacing.
     ImRect bb_with_spacing = bb;
     ImRect bb_with_spacing = bb;
@@ -7208,7 +7390,12 @@ void ImGui::Separator()
     if (window->DC.ColumnsCount > 1)
     if (window->DC.ColumnsCount > 1)
         PopClipRect();
         PopClipRect();
 
 
-    const ImRect bb(ImVec2(window->Pos.x, window->DC.CursorPos.y), ImVec2(window->Pos.x + window->Size.x, window->DC.CursorPos.y));
+    float x1 = window->Pos.x;
+    float x2 = window->Pos.x + window->Size.x;
+    if (!window->DC.GroupStack.empty())
+        x1 += window->DC.ColumnsStartX;
+
+    const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y));
     ItemSize(ImVec2(0.0f, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
     ItemSize(ImVec2(0.0f, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
     if (!ItemAdd(bb, NULL))
     if (!ItemAdd(bb, NULL))
     {
     {
@@ -7448,6 +7635,7 @@ static float GetDraggedColumnOffset(int column_index)
     // window creates a feedback loop because we store normalized positions/ So while dragging we enforce absolute positioning
     // window creates a feedback loop because we store normalized positions/ So while dragging we enforce absolute positioning
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
+    IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets.
     IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index));
     IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index));
 
 
     float x = g.IO.MousePos.x + g.ActiveClickDeltaToCenter.x;
     float x = g.IO.MousePos.x + g.ActiveClickDeltaToCenter.x;
@@ -7572,7 +7760,9 @@ void ImGui::Columns(int columns_count, const char* id, bool border)
     }
     }
 
 
     // Set state for first column
     // Set state for first column
+    ImGui::PushID(0x11223344); // Differentiate column ID with an arbitrary/random prefix for cases where users name their columns set the same as another non-scope widget
     window->DC.ColumnsSetID = window->GetID(id ? id : "");
     window->DC.ColumnsSetID = window->GetID(id ? id : "");
+    ImGui::PopID();
     window->DC.ColumnsCurrent = 0;
     window->DC.ColumnsCurrent = 0;
     window->DC.ColumnsCount = columns_count;
     window->DC.ColumnsCount = columns_count;
     window->DC.ColumnsShowBorders = border;
     window->DC.ColumnsShowBorders = border;
@@ -7780,10 +7970,7 @@ void ImDrawList::PushClipRectFullScreen()
 
 
     // This would be more correct but we're not supposed to access ImGuiState from here?
     // This would be more correct but we're not supposed to access ImGuiState from here?
     //ImGuiState& g = *GImGui;
     //ImGuiState& g = *GImGui;
-    //if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
-    //    PushClipRect(ImVec4(g.IO.DisplayVisibleMin.x, g.IO.DisplayVisibleMin.y, g.IO.DisplayVisibleMax.x, g.IO.DisplayVisibleMax.y));
-    //else
-    //    PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
+    //PushClipRect(GetVisibleRect());
 }
 }
 
 
 void ImDrawList::PopClipRect()
 void ImDrawList::PopClipRect()
@@ -9986,18 +10173,24 @@ void ImGui::ShowTestWindow(bool* opened)
             static int vec4i[4] = { 1, 5, 100, 255 };
             static int vec4i[4] = { 1, 5, 100, 255 };
 
 
             ImGui::InputFloat2("input float2", vec4f);
             ImGui::InputFloat2("input float2", vec4f);
+            ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
             ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
             ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
+            ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
             ImGui::InputInt2("input int2", vec4i);
             ImGui::InputInt2("input int2", vec4i);
             ImGui::SliderInt2("slider int2", vec4i, 0, 255);
             ImGui::SliderInt2("slider int2", vec4i, 0, 255);
 
 
             ImGui::InputFloat3("input float3", vec4f);
             ImGui::InputFloat3("input float3", vec4f);
+            ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
             ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
             ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
+            ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
             ImGui::InputInt3("input int3", vec4i);
             ImGui::InputInt3("input int3", vec4i);
             ImGui::SliderInt3("slider int3", vec4i, 0, 255);
             ImGui::SliderInt3("slider int3", vec4i, 0, 255);
 
 
             ImGui::InputFloat4("input float4", vec4f);
             ImGui::InputFloat4("input float4", vec4f);
+            ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
             ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
             ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
             ImGui::InputInt4("input int4", vec4i);
             ImGui::InputInt4("input int4", vec4i);
+            ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
             ImGui::SliderInt4("slider int4", vec4i, 0, 255);
             ImGui::SliderInt4("slider int4", vec4i, 0, 255);
 
 
             ImGui::Indent();
             ImGui::Indent();
@@ -10153,12 +10346,12 @@ void ImGui::ShowTestWindow(bool* opened)
             // Text
             // Text
             ImGui::Text("Two items: Hello");
             ImGui::Text("Two items: Hello");
             ImGui::SameLine();
             ImGui::SameLine();
-            ImGui::TextColored(ImVec4(1,1,0,1), "World");
+            ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
 
 
             // Adjust spacing
             // Adjust spacing
             ImGui::Text("More spacing: Hello");
             ImGui::Text("More spacing: Hello");
             ImGui::SameLine(0, 20);
             ImGui::SameLine(0, 20);
-            ImGui::TextColored(ImVec4(1,1,0,1), "World");
+            ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
 
 
             // Button
             // Button
             ImGui::AlignFirstTextHeightToWidgets();
             ImGui::AlignFirstTextHeightToWidgets();
@@ -10401,7 +10594,7 @@ void ImGui::ShowTestWindow(bool* opened)
         ImGui::Text("An extra line here.");
         ImGui::Text("An extra line here.");
         ImGui::NextColumn();
         ImGui::NextColumn();
         
         
-        ImGui::Text("World!");
+        ImGui::Text("Sailor");
         ImGui::Button("Corniflower");
         ImGui::Button("Corniflower");
         ImGui::RadioButton("radio c", &e, 2);
         ImGui::RadioButton("radio c", &e, 2);
         static float bar = 1.0f;
         static float bar = 1.0f;
@@ -10420,8 +10613,8 @@ void ImGui::ShowTestWindow(bool* opened)
         ImGui::Text("Tree items:");
         ImGui::Text("Tree items:");
         ImGui::Columns(2, "tree items");
         ImGui::Columns(2, "tree items");
         ImGui::Separator();
         ImGui::Separator();
-        if (ImGui::TreeNode("Hello")) { ImGui::BulletText("World"); ImGui::TreePop(); } ImGui::NextColumn();
-        if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Monde"); ImGui::TreePop(); } ImGui::NextColumn();
+        if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
+        if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
         ImGui::Columns(1);
         ImGui::Columns(1);
 
 
         ImGui::Separator();
         ImGui::Separator();
@@ -10601,7 +10794,7 @@ void ImGui::ShowMetricsWindow(bool* opened)
 
 
             static void NodeWindow(ImGuiWindow* window, const char* label)
             static void NodeWindow(ImGuiWindow* window, const char* label)
             {
             {
-                if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Visible, window))
+                if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
                     return;
                     return;
                 NodeDrawList(window->DrawList, "DrawList");
                 NodeDrawList(window->DrawList, "DrawList");
                 if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
                 if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
@@ -10633,7 +10826,7 @@ static void ShowExampleAppAutoResize(bool* opened)
     }
     }
 
 
     static int lines = 10;
     static int lines = 10;
-    ImGui::TextWrapped("Window will resize every-frame to the size of its content. Note that you don't want to query the window size to output your content because that would create a feedback loop.");
+    ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
     ImGui::SliderInt("Number of lines", &lines, 1, 20);
     ImGui::SliderInt("Number of lines", &lines, 1, 20);
     for (int i = 0; i < lines; i++)
     for (int i = 0; i < lines; i++)
         ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally
         ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally

+ 19 - 10
imgui.h

@@ -1,4 +1,4 @@
-// ImGui library v1.38
+// ImGui library v1.39 WIP
 // See .cpp file for documentation.
 // See .cpp file for documentation.
 // See ImGui::ShowTestWindow() for sample code.
 // See ImGui::ShowTestWindow() for sample code.
 // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
 // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase.
@@ -13,7 +13,7 @@
 #include <stdlib.h>         // NULL, malloc, free, qsort, atoi
 #include <stdlib.h>         // NULL, malloc, free, qsort, atoi
 #include <string.h>         // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
 #include <string.h>         // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
 
 
-#define IMGUI_VERSION       "1.38"
+#define IMGUI_VERSION       "1.39 WIP"
 
 
 // Define assertion handler.
 // Define assertion handler.
 #ifndef IM_ASSERT
 #ifndef IM_ASSERT
@@ -159,14 +159,14 @@ namespace ImGui
     IMGUI_API void          ShowUserGuide();                            // help block
     IMGUI_API void          ShowUserGuide();                            // help block
     IMGUI_API void          ShowStyleEditor(ImGuiStyle* ref = NULL);    // style editor block
     IMGUI_API void          ShowStyleEditor(ImGuiStyle* ref = NULL);    // style editor block
     IMGUI_API void          ShowTestWindow(bool* opened = NULL);        // test window, demonstrate ImGui features
     IMGUI_API void          ShowTestWindow(bool* opened = NULL);        // test window, demonstrate ImGui features
-    IMGUI_API void          ShowMetricsWindow(bool* opened = NULL);     // metrics window
+    IMGUI_API void          ShowMetricsWindow(bool* opened = NULL);     // metrics window for debugging imgui
 
 
     // Window
     // Window
     // See implementation in .cpp for details
     // See implementation in .cpp for details
     IMGUI_API bool          Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0);                                           // return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). 
     IMGUI_API bool          Begin(const char* name = "Debug", bool* p_opened = NULL, ImGuiWindowFlags flags = 0);                                           // return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). 
     IMGUI_API bool          Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0);   // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
     IMGUI_API bool          Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0);   // this is the older/longer API. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
     IMGUI_API void          End();
     IMGUI_API void          End();
-    IMGUI_API bool          BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);        // size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). on each axis.
+    IMGUI_API bool          BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);        // size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
     IMGUI_API bool          BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);                // "
     IMGUI_API bool          BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0);                // "
     IMGUI_API void          EndChild();
     IMGUI_API void          EndChild();
     IMGUI_API ImVec2        GetContentRegionMax();                                              // window or current column boundaries, in windows coordinates
     IMGUI_API ImVec2        GetContentRegionMax();                                              // window or current column boundaries, in windows coordinates
@@ -237,7 +237,7 @@ namespace ImGui
     IMGUI_API void          Spacing();                                                          // add vertical spacing
     IMGUI_API void          Spacing();                                                          // add vertical spacing
     IMGUI_API void          Indent();                                                           // move content position toward the right by style.IndentSpacing pixels
     IMGUI_API void          Indent();                                                           // move content position toward the right by style.IndentSpacing pixels
     IMGUI_API void          Unindent();                                                         // move content position back to the left (cancel Indent)
     IMGUI_API void          Unindent();                                                         // move content position back to the left (cancel Indent)
-    IMGUI_API void          Columns(int count = 1, const char* id = NULL, bool border=true);    // setup number of columns
+    IMGUI_API void          Columns(int count = 1, const char* id = NULL, bool border=true);    // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1).
     IMGUI_API void          NextColumn();                                                       // next column
     IMGUI_API void          NextColumn();                                                       // next column
     IMGUI_API int           GetColumnIndex();                                                   // get current column index
     IMGUI_API int           GetColumnIndex();                                                   // get current column index
     IMGUI_API float         GetColumnOffset(int column_index = -1);                             // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this
     IMGUI_API float         GetColumnOffset(int column_index = -1);                             // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this
@@ -317,9 +317,14 @@ namespace ImGui
     IMGUI_API bool          VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f");
     IMGUI_API bool          VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* display_format = "%.0f");
 
 
     // Widgets: Drags (tip: ctrl+click on a drag box to input text)
     // Widgets: Drags (tip: ctrl+click on a drag box to input text)
-    // ImGui 1.38+ work-in-progress, may change name or API.
-    IMGUI_API bool          DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f);  // If v_max >= v_max we have no bound
-    IMGUI_API bool          DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f");                                    // If v_max >= v_max we have no bound
+    IMGUI_API bool          DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f);     // If v_max >= v_max we have no bound
+    IMGUI_API bool          DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f);
+    IMGUI_API bool          DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f);
+    IMGUI_API bool          DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f);
+    IMGUI_API bool          DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f");                                       // If v_max >= v_max we have no bound
+    IMGUI_API bool          DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f");
+    IMGUI_API bool          DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f");
+    IMGUI_API bool          DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f");
 
 
     // Widgets: Input
     // Widgets: Input
     IMGUI_API bool          InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);
     IMGUI_API bool          InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);
@@ -381,7 +386,9 @@ namespace ImGui
     IMGUI_API bool          IsRootWindowFocused();                                              // is current root window focused
     IMGUI_API bool          IsRootWindowFocused();                                              // is current root window focused
     IMGUI_API bool          IsRootWindowOrAnyChildFocused();                                    // is current root window or any of its child (including current window) focused
     IMGUI_API bool          IsRootWindowOrAnyChildFocused();                                    // is current root window or any of its child (including current window) focused
     IMGUI_API bool          IsRectClipped(const ImVec2& size);                                  // test if rectangle of given size starting from cursor pos is out of clipping region. to perform coarse clipping on user's side (as an optimization)
     IMGUI_API bool          IsRectClipped(const ImVec2& size);                                  // test if rectangle of given size starting from cursor pos is out of clipping region. to perform coarse clipping on user's side (as an optimization)
-    IMGUI_API bool          IsKeyPressed(int key_index, bool repeat = true);                    // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry
+    IMGUI_API bool          IsKeyDown(int key_index);                                           // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry
+    IMGUI_API bool          IsKeyPressed(int key_index, bool repeat = true);                    // "
+    IMGUI_API bool          IsMouseDown(int button);
     IMGUI_API bool          IsMouseClicked(int button, bool repeat = false);
     IMGUI_API bool          IsMouseClicked(int button, bool repeat = false);
     IMGUI_API bool          IsMouseDoubleClicked(int button);
     IMGUI_API bool          IsMouseDoubleClicked(int button);
     IMGUI_API bool          IsMouseHoveringWindow();                                            // is mouse hovering current window ("window" in API names always refer to current window)
     IMGUI_API bool          IsMouseHoveringWindow();                                            // is mouse hovering current window ("window" in API names always refer to current window)
@@ -597,7 +604,8 @@ struct ImGuiStyle
     float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns
     float       ColumnsMinSpacing;          // Minimum horizontal spacing between two columns
     float       ScrollbarWidth;             // Width of the vertical scrollbar
     float       ScrollbarWidth;             // Width of the vertical scrollbar
     float       GrabMinSize;                // Minimum width/height of a slider or scrollbar grab
     float       GrabMinSize;                // Minimum width/height of a slider or scrollbar grab
-    ImVec2      DisplaySafeAreaPadding;     // Window positions are clamped to be visible within the display area. If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding.
+    ImVec2      DisplayWindowPadding;       // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
+    ImVec2      DisplaySafeAreaPadding;     // 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.
     ImVec4      Colors[ImGuiCol_COUNT];
     ImVec4      Colors[ImGuiCol_COUNT];
 
 
     IMGUI_API ImGuiStyle();
     IMGUI_API ImGuiStyle();
@@ -800,6 +808,7 @@ struct ImGuiStorage
     // - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application.
     // - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application.
     IMGUI_API int*    GetIntRef(ImGuiID key, int default_val = 0);
     IMGUI_API int*    GetIntRef(ImGuiID key, int default_val = 0);
     IMGUI_API float*  GetFloatRef(ImGuiID key, float default_val = 0);
     IMGUI_API float*  GetFloatRef(ImGuiID key, float default_val = 0);
+    IMGUI_API void**  GetVoidPtrRef(ImGuiID key, void* default_val = NULL);
 
 
     // Use on your own storage if you know only integer are being stored (open/close all tree nodes)
     // Use on your own storage if you know only integer are being stored (open/close all tree nodes)
     IMGUI_API void    SetAllInt(int val);
     IMGUI_API void    SetAllInt(int val);