Parcourir la source

Updated imgui.

Branimir Karadžić il y a 10 ans
Parent
commit
f05443c0e7

+ 72 - 62
3rdparty/ocornut-imgui/imgui.cpp

@@ -426,11 +426,12 @@
  - popup: border options. richer api like BeginChild() perhaps? (#197)
  - combo: sparse combo boxes (via function call?)
  - 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 (pr #203)
+ - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
  - listbox: multiple selection
  - listbox: user may want to initial scroll to focus on the one selected value?
  - listbox: keyboard navigation.
  - listbox: scrolling should track modified selection.
+ ! menus/popups: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331)
  - menus: local shortcuts, global shortcuts (#126)
  - menus: icons
  - menus: menubars: some sort of priority / effect of main menu-bar on desktop size?
@@ -1303,14 +1304,16 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
     }
 }
 
-void ImGuiTextFilter::Draw(const char* label, float width)
+bool ImGuiTextFilter::Draw(const char* label, float width)
 {
     if (width != 0.0f)
         ImGui::PushItemWidth(width);
-    ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
+    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
     if (width != 0.0f)
         ImGui::PopItemWidth();
-    Build();
+    if (value_changed)
+        Build();
+    return value_changed;
 }
 
 void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>& out)
@@ -1839,10 +1842,10 @@ void ImGui::NewFrame()
     g.IO.MousePosPrev = g.IO.MousePos;
     for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
     {
+        g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
+        g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDurationPrev[i] >= 0.0f;
         g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
         g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
-        g.IO.MouseClicked[i] = g.IO.MouseDownDuration[i] == 0.0f;
-        g.IO.MouseReleased[i] = g.IO.MouseDownDurationPrev[i] >= 0.0f && !g.IO.MouseDown[i];
         g.IO.MouseDoubleClicked[i] = false;
         if (g.IO.MouseClicked[i])
         {
@@ -2260,68 +2263,76 @@ static void PopClipRect()
     window->ClipRect = window->DrawList->_ClipRectStack.back();
 }
 
-void ImGui::Render()
+// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
+void ImGui::EndFrame()
 {
     ImGuiState& g = *GImGui;
-    IM_ASSERT(g.Initialized);                           // Forgot to call ImGui::NewFrame()
+    IM_ASSERT(g.Initialized);                       // Forgot to call ImGui::NewFrame()
+    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again
 
-    const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount);
-    g.FrameCountRendered = g.FrameCount;
+    g.FrameCountEnded = g.FrameCount;
 
-    if (first_render_of_the_frame)
-    {
-        // Hide implicit "Debug" window if it hasn't been used
-        IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin/End
-        if (g.CurrentWindow && !g.CurrentWindow->Accessed)
-            g.CurrentWindow->Active = false;
-        ImGui::End();
+    // Hide implicit "Debug" window if it hasn't been used
+    IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin/End
+    if (g.CurrentWindow && !g.CurrentWindow->Accessed)
+        g.CurrentWindow->Active = false;
+    ImGui::End();
 
-        // Click to focus window and start moving (after we're done with all our widgets)
-        if (!g.ActiveId)
-            g.MovedWindow = NULL;
-        if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
+    // Click to focus window and start moving (after we're done with all our widgets)
+    if (!g.ActiveId)
+        g.MovedWindow = NULL;
+    if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
+    {
+        if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
         {
-            if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
+            if (g.HoveredRootWindow != NULL)
             {
-                if (g.HoveredRootWindow != NULL)
-                {
-                    FocusWindow(g.HoveredWindow);
-                    if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
-                    {
-                        g.MovedWindow = g.HoveredWindow;
-                        SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
-                    }
-                }
-                else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL)
+                FocusWindow(g.HoveredWindow);
+                if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
                 {
-                    // Clicking on void disable focus
-                    FocusWindow(NULL);
+                    g.MovedWindow = g.HoveredWindow;
+                    SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
                 }
             }
+            else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL)
+            {
+                // Clicking on void disable focus
+                FocusWindow(NULL);
+            }
         }
+    }
 
-        // Sort the window list so that all child windows are after their parent
-        // We cannot do that on FocusWindow() because childs may not exist yet
-        g.WindowsSortBuffer.resize(0);
-        g.WindowsSortBuffer.reserve(g.Windows.Size);
-        for (int i = 0; i != g.Windows.Size; 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;
-            AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
-        }
-        IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong
-        g.Windows.swap(g.WindowsSortBuffer);
-
-        // Clear Input data for next frame
-        g.IO.MouseWheel = 0.0f;
-        memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
+    // Sort the window list so that all child windows are after their parent
+    // We cannot do that on FocusWindow() because childs may not exist yet
+    g.WindowsSortBuffer.resize(0);
+    g.WindowsSortBuffer.reserve(g.Windows.Size);
+    for (int i = 0; i != g.Windows.Size; 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;
+        AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
     }
+    IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong
+    g.Windows.swap(g.WindowsSortBuffer);
+
+    // Clear Input data for next frame
+    g.IO.MouseWheel = 0.0f;
+    memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
+}
+
+void ImGui::Render()
+{
+    ImGuiState& g = *GImGui;
+    IM_ASSERT(g.Initialized);   // Forgot to call ImGui::NewFrame()
+
+    if (g.FrameCountEnded != g.FrameCount)
+        ImGui::EndFrame();
+    g.FrameCountRendered = g.FrameCount;
 
     // Skip render altogether if alpha is 0.0
-    // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or respond to Begin() returning false.
+    // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false.
     if (g.Style.Alpha > 0.0f)
     {
         // Render tooltip
@@ -2361,13 +2372,13 @@ void ImGui::Render()
         for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
         {
             ImVector<ImDrawList*>& layer = g.RenderDrawLists[i];
-            if (!layer.empty())
-            {
-                memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
-                n += layer.Size;
-            }
+            if (layer.empty())
+                continue;
+            memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
+            n += layer.Size;
         }
 
+        // Draw software mouse cursor if requested
         if (g.IO.MouseDrawCursor)
         {
             const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];
@@ -2393,9 +2404,7 @@ void ImGui::Render()
 
         // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
         if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
-        {
             g.IO.RenderDrawListsFn(&g.RenderDrawData);
-        }
     }
 }
 
@@ -3431,8 +3440,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
 {
     ImGuiState& g = *GImGui;
     const ImGuiStyle& style = g.Style;
+    IM_ASSERT(name != NULL);                        // Window name required
     IM_ASSERT(g.Initialized);                       // Forgot to call ImGui::NewFrame()
-    IM_ASSERT(name != NULL);                        // Must pass a name
+    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
 
     if (flags & ImGuiWindowFlags_NoInputs)
         flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
@@ -7175,7 +7185,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         if (g.IO.InputCharacters[0])
         {
             // Process text input (before we check for Return because using some IME will effectively send a Return?)
-            if (!is_ctrl_down && !is_alt_down && is_editable)
+            if (!is_ctrl_down && is_editable)
             {
                 for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
                     if (unsigned int c = (unsigned int)g.IO.InputCharacters[n])

+ 1 - 1
3rdparty/ocornut-imgui/imgui.h

@@ -868,7 +868,7 @@ struct ImGuiTextFilter
 
     ImGuiTextFilter(const char* default_filter = "");
     void Clear() { InputBuf[0] = 0; Build(); }
-    void Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f);    // Helper calling InputText+Build
+    bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f);    // Helper calling InputText+Build
     bool PassFilter(const char* text, const char* text_end = NULL) const;
     bool IsActive() const { return !Filters.empty(); }
     IMGUI_API void Build();

+ 4 - 3
3rdparty/ocornut-imgui/imgui_demo.cpp

@@ -1382,9 +1382,10 @@ void ImGui::ShowTestWindow(bool* opened)
             ImGuiIO& io = ImGui::GetIO();
 
             ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y);
-            ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.MouseDownDuration[i]); }
-            ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text("%d", i); }
-            ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text("%d", i); }
+            ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+            ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text("b%d", i); }
+            ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+            ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text("b%d", i); }
             ImGui::Text("MouseWheel: %.1f", io.MouseWheel);
 
             ImGui::Text("Keys down:");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f)     { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }

+ 9 - 2
3rdparty/ocornut-imgui/imgui_internal.h

@@ -331,6 +331,7 @@ struct ImGuiState
 
     float                   Time;
     int                     FrameCount;
+    int                     FrameCountEnded;
     int                     FrameCountRendered;
     ImVector<ImGuiWindow*>  Windows;
     ImVector<ImGuiWindow*>  WindowsSortBuffer;
@@ -416,7 +417,7 @@ struct ImGuiState
 
         Time = 0.0f;
         FrameCount = 0;
-        FrameCountRendered = -1;
+        FrameCountEnded = FrameCountRendered = -1;
         CurrentWindow = NULL;
         FocusedWindow = NULL;
         HoveredWindow = NULL;
@@ -631,7 +632,11 @@ public:
 
 namespace ImGui
 {
-    inline    ImGuiWindow*  GetCurrentWindowRead()      { ImGuiState& g = *GImGui; return g.CurrentWindow; }        // If this ever crash it means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+    // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+    // If this ever crash because g.CurrentWindow is NULL it means that either
+    // - ImGui::NewFrame() has never been called, which is illegal.
+    // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
+    inline    ImGuiWindow*  GetCurrentWindowRead()      { ImGuiState& g = *GImGui; return g.CurrentWindow; }
     inline    ImGuiWindow*  GetCurrentWindow()          { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
     IMGUI_API ImGuiWindow*  GetParentWindow();
     IMGUI_API void          FocusWindow(ImGuiWindow* window);
@@ -639,6 +644,8 @@ namespace ImGui
     IMGUI_API void          SetActiveID(ImGuiID id, ImGuiWindow* window);
     IMGUI_API void          KeepAliveID(ImGuiID id);
 
+    IMGUI_API void          EndFrame();                 // This automatically called by Render()
+
     IMGUI_API void          ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
     IMGUI_API void          ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
     IMGUI_API bool          ItemAdd(const ImRect& bb, const ImGuiID* id);