From 16a5da9521f966ad90eef15aec012e0a07dd903f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 3 Nov 2017 20:17:13 +0100 Subject: [PATCH 01/26] RenderTriangle() minor tweak to align Left/Right and Up/Down arrow extents visually --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index daa658d7..237154fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3105,6 +3105,7 @@ void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale) case ImGuiDir_Left: r = -r; // ...fall through, no break! case ImGuiDir_Right: + center.x -= r * 0.25f; a = ImVec2(1,0) * r; b = ImVec2(-0.500f,+0.866f) * r; c = ImVec2(-0.500f,-0.866f) * r; @@ -9096,7 +9097,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo PopStyleColor(); } if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * (0.20f+0.200f), g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } return pressed; } @@ -9215,7 +9216,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), ImGuiDir_Right); + RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right); if (!enabled) PopStyleColor(); } From f0b4097c54d435d6ba9997ecad7aa434c19f5406 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 6 Nov 2017 23:55:40 +0100 Subject: [PATCH 02/26] Begin: Simplified code and fixed a bug where appending into a window a second time (from a remote window) would incorrectly overwrite RootWindow with the current window in the stack. Our docking code uses this pattern. --- imgui.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 237154fe..9c9e7b12 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4181,21 +4181,17 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) g.SetNextWindowFocus = false; } - // Update known root window (if we are a child window, otherwise window == window->RootWindow) - int root_idx, root_non_popup_idx; - for (root_idx = g.CurrentWindowStack.Size - 1; root_idx > 0; root_idx--) - if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) - break; - for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) - if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (g.CurrentWindowStack[root_non_popup_idx]->Flags & ImGuiWindowFlags_Modal)) - break; - window->ParentWindow = parent_window; - window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { + // Initialize + window->ParentWindow = parent_window; + window->RootWindow = !(flags & ImGuiWindowFlags_ChildWindow) ? window : parent_window->RootWindow; + window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + //window->RootNavWindow = window; + //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) + // window->RootNavWindow = window->RootNavWindow->ParentWindow; + window->Active = true; window->OrderWithinParent = 0; window->BeginCount = 0; From 2c7ba21417dbc82e277e223e556e5a29a0674798 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 11:37:38 +0100 Subject: [PATCH 03/26] Fixed auto-resize allocating too much space for scrollbar when SizeContents is bigger than maximum window size (fixes c0547d358d746699f8d46a4996e49fdac8c55748) (#1417) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 9c9e7b12..d762910a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4039,7 +4039,7 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window) if (size_auto_fit_after_constraint.x < window->SizeContents.x && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)) size_auto_fit.y += style.ScrollbarSize; if (size_auto_fit_after_constraint.y < window->SizeContents.y && !(flags & ImGuiWindowFlags_NoScrollbar)) - size_auto_fit.x += style.ScrollbarSize * 2.0f; + size_auto_fit.x += style.ScrollbarSize; size_auto_fit.y = ImMax(size_auto_fit.y - style.ItemSpacing.y, 0.0f); } return size_auto_fit; From 8e6adc78afe090fe012ec50625aad82666303f86 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 11:38:14 +0100 Subject: [PATCH 04/26] Examples: Constrained Resize: Added more test cases (for #1417) --- imgui_demo.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0d6a4423..7f45c50e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2145,31 +2145,40 @@ static void ShowExampleAppConstrainedResize(bool* p_open) static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } }; + static bool auto_resize = false; static int type = 0; + static int display_lines = 10; if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 - if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400 - if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500 + if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500 + if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step - if (ImGui::Begin("Example: Constrained Resize", p_open)) + ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0; + if (ImGui::Begin("Example: Constrained Resize", p_open, flags)) { const char* desc[] = { "Resize vertical only", "Resize horizontal only", "Width > 100, Height > 100", - "Width 300-400", + "Width 400-500", + "Height 400-500", "Custom: Always Square", "Custom: Fixed Steps (100)", }; - ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); - if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200,200)); } ImGui::SameLine(); - if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500,500)); } ImGui::SameLine(); - if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800,200)); } - for (int i = 0; i < 10; i++) - ImGui::Text("Hello, sailor! Making this line long enough for the example."); + if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine(); + if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine(); + if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); } + ImGui::PushItemWidth(200); + ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); + ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100); + ImGui::PopItemWidth(); + ImGui::Checkbox("Auto-resize", &auto_resize); + for (int i = 0; i < display_lines; i++) + ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, ""); } ImGui::End(); } From 571b08f31528cf13fe6c8885a8dc13c174aeced3 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 13:59:55 +0100 Subject: [PATCH 05/26] Internal: FindWindowByName() faster and doesn't touch every windows --- imgui.cpp | 10 +++------- imgui_internal.h | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d762910a..ce03aafb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3920,13 +3920,9 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, ImGuiWindow* ImGui::FindWindowByName(const char* name) { - // FIXME-OPT: Store sorted hashes -> pointers so we can do a bissection in a contiguous block ImGuiContext& g = *GImGui; ImGuiID id = ImHash(name, 0); - for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i]->ID == id) - return g.Windows[i]; - return NULL; + return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); } static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags) @@ -3937,6 +3933,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); IM_PLACEMENT_NEW(window) ImGuiWindow(name); window->Flags = flags; + g.WindowsById.SetVoidPtr(window->ID, window); if (flags & ImGuiWindowFlags_NoSavedSettings) { @@ -5280,8 +5277,7 @@ bool ImGui::IsWindowAppearing() void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) { - ImGuiWindow* window = FindWindowByName(name); - if (window) + if (ImGuiWindow* window = FindWindowByName(name)) SetWindowCollapsed(window, collapsed, cond); } diff --git a/imgui_internal.h b/imgui_internal.h index ccfc3bf4..9781f822 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -422,6 +422,7 @@ struct ImGuiContext ImVector Windows; ImVector WindowsSortBuffer; ImVector CurrentWindowStack; + ImGuiStorage WindowsById; ImGuiWindow* CurrentWindow; // Being drawn into ImGuiWindow* NavWindow; // Nav/focused window for navigation ImGuiWindow* HoveredWindow; // Will catch mouse inputs From 1870738880246c18c150d19dbac8a35426688997 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 14:05:48 +0100 Subject: [PATCH 06/26] LowerBound() minor tweaks --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ce03aafb..69ee04d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1385,10 +1385,10 @@ static ImVector::iterator LowerBound(ImVector::iterator first = data.begin(); ImVector::iterator last = data.end(); - int count = (int)(last - first); + size_t count = (size_t)(last - first); while (count > 0) { - int count2 = count / 2; + size_t count2 = count >> 1; ImVector::iterator mid = first + count2; if (mid->key < key) { From aae52522c3d6ebd35dedb0f62e8e23cdc5768c1d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 13:11:45 +0100 Subject: [PATCH 07/26] Internals: Remove requirement to define IMGUI_DEFINE_PLACEMENT_NEW (#1103) --- imgui_internal.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 9781f822..a5d87722 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2,10 +2,9 @@ // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! -// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) +// Set: // #define IMGUI_DEFINE_MATH_OPERATORS -// Define IM_PLACEMENT_NEW() macro helper. -// #define IMGUI_DEFINE_PLACEMENT_NEW +// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators) #pragma once @@ -159,12 +158,10 @@ static inline float ImLinearSweep(float current, float target, float speed) // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -#ifdef IMGUI_DEFINE_PLACEMENT_NEW struct ImPlacementNewDummy {}; inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; } inline void operator delete(void*, ImPlacementNewDummy, void*) {} #define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR) -#endif //----------------------------------------------------------------------------- // Types From 41862b8c0e9f651a253de45c2b7e982c19c9ea9d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 16:41:58 +0100 Subject: [PATCH 08/26] ButtonBehavior: Fixed ImGuiButtonFlags_NoHoldingActiveID from incorrectly setting ActiveIdClickOffset, which probably have no known effect, but it is more correct this way. (#1418) --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 69ee04d9..ba212d73 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5835,11 +5835,15 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { pressed = true; if (flags & ImGuiButtonFlags_NoHoldingActiveID) + { ClearActiveID(); + } else + { SetActiveID(id, window); // Hold on ID + g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; + } FocusWindow(window); - g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { From 2ab27be3de2cb794f3be360f5031371460420527 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 7 Nov 2017 22:23:02 +0100 Subject: [PATCH 09/26] Child window with MenuBar use regular WindowPadding.y so layout look consistent in child or in a regular window. --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ba212d73..d9ccc433 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4251,7 +4251,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = style.WindowPadding; + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) + window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcSizeAutoFit(window); From 9ac8820ee2ad3b569b592519a50b6dad4607eb04 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 8 Nov 2017 22:32:22 +0100 Subject: [PATCH 10/26] Fixed non-pixel aligned bounding box of window resize grip, / which triumphally led to any re-arrangement of operations inside the resize grip code outputting non-exact size_target values which led to unstable window position because clamping code uses size in a subtraction, etc etc. Lovely how a whole system can be made to act weird with a single bad input. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index d9ccc433..0ded20c0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4386,7 +4386,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Manual resize // Using the FlattenChilds button flag, we make the resize button accessible even if we are hovering over a child window const ImVec2 br = window->Rect().GetBR(); - const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); + const ImRect resize_rect(br - ImFloor(ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f)), br); const ImGuiID resize_id = window->GetID("#RESIZE"); bool hovered, held; ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); From a4cc3d4637f7aa3aac7c730c6d21370c8737a76f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 8 Nov 2017 22:36:31 +0100 Subject: [PATCH 11/26] Minor tweaks/comments. Note that the reordering the one subtraction caused subtle havoc before the patch in 9ac8820ee2ad3b569b592519a50b6dad4607eb04. --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0ded20c0..d64ac6d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4404,7 +4404,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - size_target = (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos; + size_target = (g.IO.MousePos - g.ActiveIdClickOffset - window->Pos) + resize_rect.GetSize(); } if (size_target.x != FLT_MAX && size_target.y != FLT_MAX) @@ -10456,8 +10456,8 @@ void ImGui::EndColumns() { float x = window->Pos.x + GetColumnOffset(i); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const float column_w = 4.0f; // Width for interaction - const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); + const float column_hw = 4.0f; // Half-width for interaction + const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; @@ -10468,7 +10468,7 @@ void ImGui::EndColumns() if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; if (held && g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). + g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). if (held) dragging_column = i; } From 2df8fa95dfe3463ece78c56b02dc815c3e71331a Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 8 Nov 2017 23:17:08 +0100 Subject: [PATCH 12/26] Fixed vertical scrollbar flickering/appearing, typically when manually resizing and using a pattern of filling available height (e.g. full sized BeginChild). THIS IS A GREAT FIX, this glitch was nasty and annoying (and yet somehow nobody reported it?). Hopefully haven't broken anything else... --- imgui.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d64ac6d3..35e30968 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4232,10 +4232,21 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // SIZE - // Save contents size from last frame for auto-fitting (unless explicitly specified) + // Update contents size from last frame for auto-fitting (unless explicitly specified) window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x)); window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y)); + // Update scrollbar status based on the Size that was effective during last frame (and not the upcoming Size which we are updating below), so that user code consuming exactly the available size won't trigger scrollbars when e.g. manually resizing. + if (!window->Collapsed) + { + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + if (window->ScrollbarX && !window->ScrollbarY) + window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); + window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; + } + // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) if (window->HiddenFrames > 0) window->HiddenFrames--; @@ -4416,14 +4427,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) title_bar_rect = window->TitleBarRect(); } - // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); - if (window->ScrollbarX && !window->ScrollbarY) - window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); - window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); - window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; - // Window background, Default Alpha ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); From 8451855a3075b14b653a561c37a7ba3eb80431a9 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 9 Nov 2017 20:08:29 +0100 Subject: [PATCH 13/26] ButtonBehavior: Fixed ImGuiButtonFlags_AllowOverlapMode to avoid temporarily activating widgets on click before they have been correctly double-hovered. (#319, #600) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 35e30968..17f42f2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5821,6 +5821,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) g.HoveredWindow = backup_hovered_window; + // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. + if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + hovered = false; + if (hovered) { if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) @@ -5880,10 +5884,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } } - // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) - hovered = pressed = held = false; - if (out_hovered) *out_hovered = hovered; if (out_held) *out_held = held; From ba09de3a392fa3a0395aa3aa1101f1b90121cc0d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 10 Nov 2017 11:37:27 +0100 Subject: [PATCH 14/26] Begin: Fixed appending into a child window with a second Begin() from a different window stack querying the wrong window for the window->Collapsed test. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 17f42f2a..dc501d46 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4106,12 +4106,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) else flags = window->Flags; + // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack + ImGuiWindow* parent_window = first_begin_of_the_frame ? (!g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; + IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); + // Add to stack - ImGuiWindow* parent_window = !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL; g.CurrentWindowStack.push_back(window); SetCurrentWindow(window); CheckStacksSize(window, true); - IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) From 9daac64ff810d5237e1256c9192a66b8aac06cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 10 Nov 2017 22:59:06 -0800 Subject: [PATCH 15/26] Clean g.WindowsById storage on shutdown. --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index dc501d46..2a5195fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2462,6 +2462,7 @@ void ImGui::Shutdown() g.WindowsSortBuffer.clear(); g.CurrentWindow = NULL; g.CurrentWindowStack.clear(); + g.WindowsById.Clear(); g.NavWindow = NULL; g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; From 161670418b00aef7207027cac208dc12eb45ff28 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Nov 2017 16:20:34 +0100 Subject: [PATCH 16/26] Update documentation for extra fonts --- extra_fonts/README.txt | 51 ++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index 77fdaa6c..a4136083 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -1,6 +1,8 @@ - The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files. - The files in this folder are only provided as a convenience, you can use any .TTF/.OTF. + The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default. + We embed the font in source code so you can use Dear ImGui without any file system access. + You may also load external .TTF/.OTF files. + The files in this folder are suggested fonts, provided as a convenience. (Note: .OTF support in stb_truetype.h currently doesn't appear to load every font) Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). @@ -12,6 +14,7 @@ Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application. A common pattern is to merge the icon font within your main font, so you can refer to the icons directly from your strings without having to change fonts back and forth. To refer to the icon from your C++ code, you can use headers files created by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders + See Links below for other icons fonts and related tools. // Merge icons into default tool font #include "IconsFontAwesome.h" @@ -40,7 +43,7 @@ ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); - Detailed options: + Advanced options: ImFontConfig config; config.OversampleH = 3; @@ -106,17 +109,23 @@ REMAPPING CODEPOINTS --------------------------------- - All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese CP-1251 for Cyrillic) will NOT work! + All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese, or CP-1251 for Cyrillic) will NOT work! In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - You can also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. + e.g. + u8"hello" + u8"こんにちは" + You may also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. --------------------------------- EMBEDDING FONT IN SOURCE CODE --------------------------------- - Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array. + Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code. See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool. + You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README). + The tool optionally used Base85 encoding to reduce the size of _source code_ but the read-only arrays will be about 20% bigger. + Then load the font with: ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...); @@ -164,36 +173,40 @@ --------------------------------- - LINKS + LINKS & OTHER FONTS --------------------------------- - Icon fonts + (Icons) Icon fonts https://fortawesome.github.io/Font-Awesome/ https://github.com/SamBrishes/kenney-icon-font https://design.google.com/icons/ + You can use https://github.com/juliettef/IconFontCppHeaders for C/C++ header files with name #define to access icon codepoint in source code. - IcoMoon - Custom Icon font builder + (Icons) IcoMoon - Custom Icon font builder https://icomoon.io/app - Typefaces for source code beautification - https://github.com/chrissimpkins/codeface + (Regular) Open Sans Fonts + https://fonts.google.com/specimen/Open+Sans + + (Regular) Google Noto Fonts (worldwide languages) + https://www.google.com/get/noto/ - Programmation fonts + (Monospace) Typefaces for source code beautification + https://github.com/chrissimpkins/codeface + + (Monospace) Programmation fonts http://s9w.github.io/font_compare/ - Proggy Programming Fonts + (Monospace) Proggy Programming Fonts http://upperbounds.net - Inconsolata + (Monospace) Inconsolata http://www.levien.com/type/myfonts/inconsolata.html - Google Noto Fonts (worldwide languages) - https://www.google.com/get/noto/ - - Adobe Source Code Pro: Monospaced font family for user interface and coding environments + (Monospace) Adobe Source Code Pro: Monospaced font family for user interface and coding environments https://github.com/adobe-fonts/source-code-pro - Monospace/Fixed Width Programmer's Fonts + (Monospace) Monospace/Fixed Width Programmer's Fonts http://www.lowing.org/fonts/ (Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need. From 631bd8a9f8492778ddd10f4ed23f036c377f71fd Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Nov 2017 18:12:33 +0100 Subject: [PATCH 17/26] Added bindings --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 306a8e54..f5da3b35 100644 --- a/README.md +++ b/README.md @@ -55,15 +55,17 @@ Integrating Dear ImGui within your custom engine is a matter of wiring mouse/key _NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ Languages: -- C (cimgui): thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui -- C#/.Net (ImGui.NET): An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET -- D (DerelictImgui): Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui +- C (cimgui): https://github.com/Extrawurst/cimgui +- C#/.Net (ImGui.NET): https://github.com/mellinoe/ImGui.NET +- ChaiScript: https://github.com/JuJuBoSc/imgui-chaiscript +- D (DerelictImgui): https://github.com/Extrawurst/DerelictImgui - Go (go-imgui): https://github.com/Armored-Dragon/go-imgui - Lua: https://github.com/patrickriordan/imgui_lua_bindings -- Pascal (imgui-pas) https://github.com/dpethes/imgui-pas -- Python (CyImGui): Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui -- Python (pyimgui): Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui -- Rust (imgui-rs): Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs +- Odin: https://github.com/ThisDrunkDane/odin-dear_imgui +- Pascal (imgui-pas): https://github.com/dpethes/imgui-pas +- Python (CyImGui): https://github.com/chromy/cyimgui +- Python (pyimgui): https://github.com/swistakm/pyimgui +- Rust (imgui-rs): https://github.com/Gekkio/imgui-rs Frameworks: - Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples @@ -78,6 +80,7 @@ Frameworks: - Irrlicht (IrrIMGUI): https://github.com/ZahlGraf/IrrIMGUI - Ogre: https://bitbucket.org/LMCrashy/ogreimgui/src - openFrameworks (ofxImGui): https://github.com/jvcleave/ofxImGui +- OpenSceneGraph/OSG: https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c - LÖVE: https://github.com/slages/love-imgui - NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example - Qt3d https://github.com/alpqr/imgui-qt3d From a1c736fa6aec984c5b2b6421b196a82a38e20851 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Nov 2017 18:22:00 +0100 Subject: [PATCH 18/26] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f5da3b35..d44ec576 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,8 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This - [Nicolas Guillemot's CppCon'16 flashtalk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). - [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/). +See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) for an incomplete list of software which are publicly known to use dear migui. + See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks. Frequently Asked Question (FAQ) From 669498ff26040636a27ea44a7129a223c9701601 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 12 Nov 2017 16:03:09 +0100 Subject: [PATCH 19/26] Added io.OptNoCursorBlink option to disable cursor blinking. (#1427). Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should affect users as the compile-time default is usually enough. (#473, #650) --- imgui.cpp | 27 +++++++++++++++------------ imgui.h | 3 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a5195fe..1f9100c0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -774,7 +774,15 @@ ImGuiIO::ImGuiIO() DisplayFramebufferScale = ImVec2(1.0f, 1.0f); DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); - // User functions + // Advanced/subtle behaviors +#ifdef __APPLE__ + OptMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag +#else + OptMacOSXBehaviors = false; +#endif + OptNoCursorBlink = false; + + // Settings (User Functions) RenderDrawListsFn = NULL; MemAllocFn = malloc; MemFreeFn = free; @@ -790,11 +798,6 @@ ImGuiIO::ImGuiIO() MouseDragThreshold = 6.0f; for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; - - // Set OS X style defaults based on __APPLE__ compile time flag -#ifdef __APPLE__ - OSXBehaviors = true; -#endif } // Pass in translated ASCII characters for text input. @@ -8099,7 +8102,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f)); - const bool osx_double_click_selects_words = io.OSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text + const bool osx_double_click_selects_words = io.OptMacOSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text if (select_all || (hovered && !osx_double_click_selects_words && io.MouseDoubleClicked[0])) { edit_state.SelectAll(); @@ -8151,9 +8154,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { // Handle key-presses const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); - const bool is_shortcut_key_only = (io.OSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl - const bool is_wordmove_key_down = io.OSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl - const bool is_startend_key_down = io.OSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End + const bool is_shortcut_key_only = (io.OptMacOSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl + const bool is_wordmove_key_down = io.OptMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl + const bool is_startend_key_down = io.OptMacOSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } @@ -8167,7 +8170,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (!edit_state.HasSelection()) { if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT); - else if (io.OSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT); + else if (io.OptMacOSXBehaviors && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT); } edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } @@ -8491,7 +8494,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); // Draw blinking cursor - bool cursor_is_visible = (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; + bool cursor_is_visible = (g.IO.OptNoCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) diff --git a/imgui.h b/imgui.h index 9a1a159a..68d53dce 100644 --- a/imgui.h +++ b/imgui.h @@ -803,7 +803,8 @@ struct ImGuiIO ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize // Advanced/subtle behaviors - bool OSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl + bool OptMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl + bool OptNoCursorBlink; // = false // Disable blinking cursor //------------------------------------------------------------------ // Settings (User Functions) From 30bf40195bc0d3e4668ddb39db25344a622593e4 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 12 Nov 2017 16:06:44 +0100 Subject: [PATCH 20/26] io.OptNoCursorBlink -> io.OptCursorBlink (#1427) --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1f9100c0..5f5a80a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -780,7 +780,7 @@ ImGuiIO::ImGuiIO() #else OptMacOSXBehaviors = false; #endif - OptNoCursorBlink = false; + OptCursorBlink = true; // Settings (User Functions) RenderDrawListsFn = NULL; @@ -8494,7 +8494,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + edit_state.CurLenA, 0.0f, is_multiline ? NULL : &clip_rect); // Draw blinking cursor - bool cursor_is_visible = (g.IO.OptNoCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; + bool cursor_is_visible = (!g.IO.OptCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || fmodf(g.InputTextState.CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll; ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f); if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) diff --git a/imgui.h b/imgui.h index 68d53dce..162ded07 100644 --- a/imgui.h +++ b/imgui.h @@ -804,7 +804,7 @@ struct ImGuiIO // Advanced/subtle behaviors bool OptMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl - bool OptNoCursorBlink; // = false // Disable blinking cursor + bool OptCursorBlink; // = true // Enable blinking cursor, for users who consider it annoying. //------------------------------------------------------------------ // Settings (User Functions) From 4d00dd8326b288aa0ff87ad6de4975d0578cfd56 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Nov 2017 15:15:48 +0100 Subject: [PATCH 21/26] Fixed scrollbar flickering on/off when uncollapsing a window (fixes 2df8fa95dfe3463ece78c56b02dc815c3e71331a) --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5f5a80a7..a9880617 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4245,10 +4245,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update scrollbar status based on the Size that was effective during last frame (and not the upcoming Size which we are updating below), so that user code consuming exactly the available size won't trigger scrollbars when e.g. manually resizing. if (!window->Collapsed) { - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->SizeFull.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); if (window->ScrollbarX && !window->ScrollbarY) - window->ScrollbarY = (window->SizeContents.y > window->Size.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarY = (window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; } From 3e06450d276eefcd7bb368badab67e766d5a5751 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 11 Nov 2017 16:58:43 +0100 Subject: [PATCH 22/26] Internals: Added ArrowButton() helper. --- imgui.cpp | 26 ++++++++++++++++++++++++++ imgui_internal.h | 1 + 2 files changed, 27 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index a9880617..55806a38 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5995,6 +5995,32 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) return pressed; } +// [Internal] +bool ImGui::ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return false; + + const ImGuiStyle& style = g.Style; + + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + padding.x * 2.0f, g.FontSize + padding.y * 2.0f)); + ItemSize(bb, style.FramePadding.y); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); + + const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); + RenderTriangle(bb.Min + padding, dir, 1.0f); + + return pressed; +} + void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui_internal.h b/imgui_internal.h index a5d87722..85eced9d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -838,6 +838,7 @@ namespace ImGui IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); + IMGUI_API bool ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFlags flags = 0); IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); From 852ece3a0e29a27771148c95fda51ba5e4e65e0c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 13 Nov 2017 16:04:03 +0100 Subject: [PATCH 23/26] Fixed build (3e06450d276eefcd7bb368badab67e766d5a5751 not meant for master branch, but ok) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 55806a38..b085efe1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6014,7 +6014,9 @@ bool ImGui::ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFla bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); +#ifdef IMGUI_HAS_NAV RenderNavHighlight(bb, id); +#endif RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); RenderTriangle(bb.Min + padding, dir, 1.0f); From 0858c3d7cbc208223563f52202cb0cccb970622b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Nov 2017 22:21:38 +0100 Subject: [PATCH 24/26] Demo: Custom Rendering: Fixed clipping rectangle extruding out of parent window. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7f45c50e..f6918f57 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2327,7 +2327,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) points.pop_back(); } } - draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.) + draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y), true); // clip lines within the canvas (if we resize it, etc.) for (int i = 0; i < points.Size - 1; i += 2) draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f); draw_list->PopClipRect(); From 6001d9c7a46f70bb029aa779c42fafd3c2b22652 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Nov 2017 22:40:57 +0100 Subject: [PATCH 25/26] Columns: Clipping columns borders on Y axis on CPU because some GPU drivers appears to be unhappy with triangle spanning large regions (not sure why tbh). (#125) Demo: Columns: Adding a billion of extra lines and using clipper. --- imgui.cpp | 3 ++- imgui_demo.cpp | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b085efe1..b828d0e9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10511,9 +10511,10 @@ void ImGui::EndColumns() } // Draw column + // We clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col); } // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f6918f57..d9ccad31 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1652,14 +1652,19 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Horizontal Scrolling")) { ImGui::SetNextWindowContentWidth(1500); - ImGui::BeginChild("##scrollingregion", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Columns(10); - for (int i = 0; i < 20; i++) - for (int j = 0; j < 10; j++) - { - ImGui::Text("Line %d Column %d...", i, j); - ImGui::NextColumn(); - } + int ITEMS_COUNT = 2000; + ImGuiListClipper clipper(ITEMS_COUNT); // Also demonstrate using the clipper for large list + while (clipper.Step()) + { + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + for (int j = 0; j < 10; j++) + { + ImGui::Text("Line %d Column %d...", i, j); + ImGui::NextColumn(); + } + } ImGui::Columns(1); ImGui::EndChild(); ImGui::TreePop(); From 64e79035d5133cf15de41aab0ec9a43bcd4ad08a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Nov 2017 23:17:28 +0100 Subject: [PATCH 26/26] Scrollbar flicker fix for menus/popups (fixes 4d00dd8326b288aa0ff87ad6de4975d0578cfd56 and 2df8fa95dfe3463ece78c56b02dc815c3e71331a). Hopefully right this time. --- imgui.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b828d0e9..f0808585 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4242,17 +4242,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->SizeContents.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.x - window->Pos.x) + window->Scroll.x)); window->SizeContents.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : ((window_is_new ? 0.0f : window->DC.CursorMaxPos.y - window->Pos.y) + window->Scroll.y)); - // Update scrollbar status based on the Size that was effective during last frame (and not the upcoming Size which we are updating below), so that user code consuming exactly the available size won't trigger scrollbars when e.g. manually resizing. - if (!window->Collapsed) - { - window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->SizeFull.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); - if (window->ScrollbarX && !window->ScrollbarY) - window->ScrollbarY = (window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); - window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); - window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; - } - // Hide popup/tooltip window when first appearing while we measure size (because we recycle them) if (window->HiddenFrames > 0) window->HiddenFrames--; @@ -4303,7 +4292,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Apply minimum/maximum window size constraints and final size window->SizeFull = CalcSizeFullWithConstraint(window, window->SizeFull); window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; - + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) + window->Size = window->SizeFull; + + // SCROLLBAR STATUS + + // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size). We need to do this before manual resize (below) is effective. + if (!window->Collapsed) + { + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->SizeFull.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + if (window->ScrollbarX && !window->ScrollbarY) + window->ScrollbarY = (window->SizeContents.y > window->SizeFull.y + style.ItemSpacing.y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); + window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; + } + // POSITION // Position child window @@ -4316,7 +4320,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { IM_ASSERT(window_size_set_by_api); // Submitted by BeginChild() window->Pos = window->PosFloat = parent_window->DC.CursorPos; - window->Size = window->SizeFull; } const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFrames == 0); @@ -4485,6 +4488,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ContentsRegionRect.Max.y = -window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y)); // Setup drawing context + // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) window->DC.IndentX = 0.0f + window->WindowPadding.x - window->Scroll.x; window->DC.GroupOffsetX = 0.0f; window->DC.ColumnsOffsetX = 0.0f;