From c077dd4872f435dd959feb024e5a9adb2c7df20c Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 31 Aug 2019 19:59:51 +0200 Subject: [PATCH 01/14] Fixed missing IMGUI_API for IsMouseDragPastThreshold(). --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index e9139d60..f13aeedc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1579,7 +1579,7 @@ namespace ImGui IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel); // Inputs - inline bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); + IMGUI_API bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { const int key_index = GImGui->IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } inline bool IsNavInputDown(ImGuiNavInput n) { return GImGui->IO.NavInputs[n] > 0.0f; } inline bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; } From cc288e073c64114058269d227d4038cf211db2e5 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Sep 2019 12:08:23 +0200 Subject: [PATCH 02/14] Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_opengl3.cpp | 24 +++++++++--------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a34aef92..09381fd5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,8 @@ Other Changes: - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636) +- Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() + before ImGui_ImplOpenGL3_NewFrame() if for some reason they wanted. - Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, would generally make the debug layer complain (Added in 1.72). - Backends: Vulkan: Added support for specifying multisample count. diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 9585215c..199638e8 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. @@ -164,7 +165,7 @@ void ImGui_ImplOpenGL3_Shutdown() void ImGui_ImplOpenGL3_NewFrame() { - if (!g_FontTexture) + if (!g_ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } @@ -613,20 +614,13 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() void ImGui_ImplOpenGL3_DestroyDeviceObjects() { - if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); - if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); - g_VboHandle = g_ElementsHandle = 0; - - if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); - if (g_VertHandle) glDeleteShader(g_VertHandle); - g_VertHandle = 0; - - if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); - if (g_FragHandle) glDeleteShader(g_FragHandle); - g_FragHandle = 0; - - if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); - g_ShaderHandle = 0; + if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; } + if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; } + if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); } + if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); } + if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; } + if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; } + if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; } ImGui_ImplOpenGL3_DestroyFontsTexture(); } From 3cf519c9cbbfc2f4e91883d8f14e62e82e5d6765 Mon Sep 17 00:00:00 2001 From: Bagrat Dabaghyan Date: Mon, 16 Sep 2019 06:03:42 +0400 Subject: [PATCH 03/14] Fix DragScalar for unsigned types (#2780) decreasing the value was broken on arm64 --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 09381fd5..cf03be73 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Other Changes: Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. +- DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a91268b3..e3441ac0 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1975,12 +1975,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); - v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); + v_cur = v_min + (SIGNEDTYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); v_old_ref_for_accum_remainder = v_old_norm_curved; } else { - v_cur += (TYPE)g.DragCurrentAccum; + v_cur += (SIGNEDTYPE)g.DragCurrentAccum; } // Round to user desired precision based on format string From b05f6f6f502752586bb82afb01b942475953677e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 9 Sep 2019 18:09:41 +0900 Subject: [PATCH 04/14] Nav, Scrolling: Added support for Home/End key. (#787) --- docs/CHANGELOG.txt | 1 + docs/TODO.txt | 7 +++-- imgui.cpp | 73 ++++++++++++++++++++++++++++++++++------------ imgui_internal.h | 5 ++-- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cf03be73..5bc49ac7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -34,6 +34,7 @@ HOW TO UPDATE? ----------------------------------------------------------------------- Other Changes: +- Nav, Scrolling: Added support for Home/End key. (#787) - ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711) Note that some elements won't accurately fade down with the same intensity, and the color wheel when enabled will have small overlap glitches with (style.Alpha < 1.0). diff --git a/docs/TODO.txt b/docs/TODO.txt index f289ebab..70c64c40 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -300,12 +300,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer? - font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16 bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8? + - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?) + - nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ? + - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view? - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window" - nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping(). - nav: patterns to make it possible for arrows key to update selection - - nav: restore/find nearest navid when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) + - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem - - nav: allow input system to be be more tolerant of io.DeltaTime=0.0f - nav: ESC within a menu of a child window seems to exit the child window. - nav: NavFlattened: ESC on a flattened child should select something. - nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child. @@ -323,7 +325,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. - - nav: configuration flag to disable global shortcuts (currently only CTRL-tab) ? - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) diff --git a/imgui.cpp b/imgui.cpp index 89541b2f..1dc4862a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1078,7 +1078,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& // Navigation static void NavUpdate(); static void NavUpdateWindowing(); -static void NavUpdateWindowingList(); +static void NavUpdateWindowingOverlay(); static void NavUpdateMoveResult(); static float NavUpdatePageUpPageDown(int allowed_dir_flags); static inline void NavUpdateAnyRequestFlag(); @@ -4184,8 +4184,8 @@ void ImGui::EndFrame() End(); // Show CTRL+TAB list window - if (g.NavWindowingTarget) - NavUpdateWindowingList(); + if (g.NavWindowingTarget != NULL) + NavUpdateWindowingOverlay(); // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) if (g.DragDropActive) @@ -8074,7 +8074,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); - ImGui::NavMoveRequestCancel(); + NavMoveRequestCancel(); g.NavMoveDir = move_dir; g.NavMoveClipDir = clip_dir; g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; @@ -8410,10 +8410,10 @@ static void ImGui::NavUpdate() g.NavMoveRequestFlags = ImGuiNavMoveFlags_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); - ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); + ImVec2 delta_scroll; + if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge) + { + float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f; + delta_scroll.y = result->Window->Scroll.y - scroll_target; + SetScrollY(result->Window, scroll_target); + } + else + { + ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); + delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); + } // Offset our result position so mouse position can be applied immediately after in NavUpdate() result->RectRel.TranslateX(-delta_scroll.x); @@ -8565,6 +8576,7 @@ static void ImGui::NavUpdateMoveResult() g.NavMoveFromClampedRefRect = false; } +// Handle PageUp/PageDown/Home/End keys static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) { ImGuiContext& g = *GImGui; @@ -8574,9 +8586,11 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) return 0.0f; ImGuiWindow* window = g.NavWindow; - bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); - bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); - if (page_up_held != page_down_held) // If either (not both) are pressed + const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); + const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down)); + if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed { if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) { @@ -8585,26 +8599,49 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); + else if (home_pressed) + SetScrollY(window, 0.0f); + else if (end_pressed) + SetScrollY(window, window->ScrollMax.y); } else { - const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; + ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); float nav_scoring_rect_offset_y = 0.0f; if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) { nav_scoring_rect_offset_y = -page_offset_y; - g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Up; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) { nav_scoring_rect_offset_y = +page_offset_y; - g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item) + g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Down; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; } + else if (home_pressed) + { + // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y + // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result. + // Preserve current horizontal position if we have any. + nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y; + if (nav_rect_rel.IsInverted()) + nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; + g.NavMoveDir = ImGuiDir_Down; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; + } + else if (end_pressed) + { + nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y; + if (nav_rect_rel.IsInverted()) + nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; + g.NavMoveDir = ImGuiDir_Up; + g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge; + } return nav_scoring_rect_offset_y; } } @@ -8800,7 +8837,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) } // Overlay displayed when using CTRL+TAB. Called by EndFrame(). -void ImGui::NavUpdateWindowingList() +void ImGui::NavUpdateWindowingOverlay() { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget != NULL); diff --git a/imgui_internal.h b/imgui_internal.h index f13aeedc..9c87d2a1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -497,7 +497,8 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) - ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5 // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. + ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. + ImGuiNavMoveFlags_ScrollToEdge = 1 << 6 }; enum ImGuiNavForward @@ -960,7 +961,7 @@ struct ImGuiContext ImGuiNavMoveFlags NavMoveRequestFlags; ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request - ImGuiDir NavMoveClipDir; + ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) From 3dcf323c35a20914930f6068002e3d4c4815bb87 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Sep 2019 19:03:20 +0200 Subject: [PATCH 05/14] Columns: Separator: Fixed a bug where non-visible separators within columns would alter the next row position differently than visible ones. Fixed rounding issues also leading to change of ScrollMax depending on visible items (in particular negative coordinate would be rounded differently) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 2 +- imgui_widgets.cpp | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5bc49ac7..6e487ae5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,8 @@ Other Changes: (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations). - TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. +- Columns, Separator: Fixed a bug where non-visible separators within columns would alter the next row position + differently than visible ones. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d5bc96c5..fd1d85a3 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1451,7 +1451,7 @@ static void ShowDemoWindowWidgets() ImGui::PushID("set2"); static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; const int rows = 3; - const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); + const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows)); for (int nx = 0; nx < 4; nx++) { if (nx > 0) ImGui::SameLine(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e3441ac0..35ce1436 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1261,7 +1261,10 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) if (!ItemAdd(bb, 0)) { if (columns) + { PopColumnsBackground(); + columns->LineMinY = window->DC.CursorPos.y; + } return; } @@ -5624,7 +5627,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). ImVec2 size; size.x = 0.0f; - size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f; + size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f); return ListBoxHeader(label, size); } From 561e7dd49098f2d6c16a21dad7701f73f78545a3 Mon Sep 17 00:00:00 2001 From: Qix Date: Tue, 17 Sep 2019 09:21:09 +0200 Subject: [PATCH 06/14] Fix signed types warning in pasteboard handler (#2786) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1dc4862a..c5039d63 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9689,7 +9689,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void*) ItemCount item_count = 0; PasteboardGetItemCount(main_clipboard, &item_count); - for (int i = 0; i < item_count; i++) + for (ItemCount i = 0; i < item_count; i++) { PasteboardItemID item_id = 0; PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id); From e7e88ed413502f1b603e35d389186d3d73a8147a Mon Sep 17 00:00:00 2001 From: NeroBurner Date: Tue, 17 Sep 2019 10:04:40 +0200 Subject: [PATCH 07/14] Examples: SDL/GLFW + OpenGL3: Fixes for Makefile (#2774) - append CXXFLAGS instead of overwriting them - add glad.c build rule --- examples/example_glfw_opengl3/Makefile | 9 +++++---- examples/example_sdl_opengl3/Makefile | 14 ++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/example_glfw_opengl3/Makefile b/examples/example_glfw_opengl3/Makefile index e8cf4614..7e17476c 100644 --- a/examples/example_glfw_opengl3/Makefile +++ b/examples/example_glfw_opengl3/Makefile @@ -35,12 +35,11 @@ CXXFLAGS += -I../libs/gl3w ## Using OpenGL loader: glew ## (This assumes a system-wide installation) -# CXXFLAGS = -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW +# CXXFLAGS += -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW ## Using OpenGL loader: glad -## (You'll also need to change the rule at line ~77 of this Makefile to compile/link glad.c/.o) # SOURCES += ../libs/glad/src/glad.c -# CXXFLAGS = -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD +# CXXFLAGS += -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD ##--------------------------------------------------------------------- ## BUILD FLAGS PER PLATFORM @@ -87,7 +86,9 @@ endif $(CXX) $(CXXFLAGS) -c -o $@ $< %.o:../libs/gl3w/GL/%.c -# %.o:../libs/glad/src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o:../libs/glad/src/%.c $(CC) $(CFLAGS) -c -o $@ $< all: $(EXE) diff --git a/examples/example_sdl_opengl3/Makefile b/examples/example_sdl_opengl3/Makefile index 76601a1b..9e84df92 100644 --- a/examples/example_sdl_opengl3/Makefile +++ b/examples/example_sdl_opengl3/Makefile @@ -35,12 +35,11 @@ CXXFLAGS += -I../libs/gl3w ## Using OpenGL loader: glew ## (This assumes a system-wide installation) -# CXXFLAGS = -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW +# CXXFLAGS += -lGLEW -DIMGUI_IMPL_OPENGL_LOADER_GLEW ## Using OpenGL loader: glad -## (You'll also need to change the rule at line ~77 of this Makefile to compile/link glad.c/.o) # SOURCES += ../libs/glad/src/glad.c -# CXXFLAGS = -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD +# CXXFLAGS += -I../libs/glad/include -DIMGUI_IMPL_OPENGL_LOADER_GLAD ##--------------------------------------------------------------------- ## BUILD FLAGS PER PLATFORM @@ -50,7 +49,7 @@ ifeq ($(UNAME_S), Linux) #LINUX ECHO_MESSAGE = "Linux" LIBS += -lGL -ldl `sdl2-config --libs` - CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags` + CXXFLAGS += `sdl2-config --cflags` CFLAGS = $(CXXFLAGS) endif @@ -59,7 +58,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs` LIBS += -L/usr/local/lib -L/opt/local/lib - CXXFLAGS += -I../libs/gl3w `sdl2-config --cflags` + CXXFLAGS += `sdl2-config --cflags` CXXFLAGS += -I/usr/local/include -I/opt/local/include CFLAGS = $(CXXFLAGS) endif @@ -68,7 +67,7 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) ECHO_MESSAGE = "MinGW" LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2` - CXXFLAGS += -I../libs/gl3w `pkg-config --cflags sdl2` + CXXFLAGS += `pkg-config --cflags sdl2` CFLAGS = $(CXXFLAGS) endif @@ -88,6 +87,9 @@ endif %.o:../libs/gl3w/GL/%.c $(CC) $(CFLAGS) -c -o $@ $< +%.o:../libs/glad/src/%.c + $(CC) $(CFLAGS) -c -o $@ $< + all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) From 404dc0367e03a220279bb34e3fe3cb758cd1d4a4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 10:41:11 +0200 Subject: [PATCH 08/14] BeginTabItem: Fixed case where right-most tab would create an extraneous draw calls (probably related to other tab fitting code in 1.73 wip) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 35ce1436..ba3bac87 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6932,7 +6932,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImRect bb(pos, pos + size); // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation) - bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x); + bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x > tab_bar->BarRect.Max.x); if (want_clip_rect) PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true); From 45405f0dc9f2a3a08883748319aeba9a5afed6e3 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Thu, 5 Sep 2019 12:59:43 +0300 Subject: [PATCH 09/14] Font: implement a way to draw narrow ellipsis without relying on hardcoded 1 pixel dots. (#2775) This changeset implements several pieces of the puzzle that add up to a narrow ellipsis rendering. ## EllipsisCodePoint `ImFontConfig` and `ImFont` received `ImWchar EllipsisCodePoint = -1;` field. User may configure `ImFontConfig::EllipsisCodePoint` a unicode codepoint that will be used for rendering narrow ellipsis. Not setting this field will automatically detect a suitable character or fall back to rendering 3 dots with minimal spacing between them. Autodetection prefers codepoint 0x2026 (narrow ellipsis) and falls back to 0x0085 (NEXT LINE) when missing. Wikipedia indicates that codepoint 0x0085 was used as ellipsis in some older windows fonts. So does default Dear ImGui font. When user is merging fonts - first configured and present ellipsis codepoint will be used, ellipsis characters from subsequently merged fonts will be ignored. ## Narrow ellipsis Rendering a narrow ellipsis is surprisingly not straightforward task. There are cases when ellipsis is bigger than the last visible character therefore `RenderTextEllipsis()` has to hide last two characters. In a subset of those cases ellipsis is as big as last visible character + space before it. `RenderTextEllipsis()` tries to work around this case by taking free space between glyph edges into account. Code responsible for this functionality is within `if (text_end_ellipsis != text_end_full) { ... }`. ## Fallback (manually rendered dots) There are cases when font does not have ellipsis character defined. In this case RenderTextEllipsis() falls back to rendering ellipsis as 3 dots, but with reduced spacing between them. 1 pixel space is used in all cases. This results in a somewhat wider ellipsis, but avoids issues where spaces between dots are uneven (visible in larger/monospace fonts) or squish dots way too much (visible in default font where dot is essentially a pixel). This fallback method obsoleted `RenderPixelEllipsis()` and this function was removed. Note that fallback ellipsis will always be somewhat wider than it could be, however it will fit in visually into every font used unlike what `RenderPixelEllipsis()` produced. --- imgui.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++---- imgui.h | 2 + imgui_draw.cpp | 39 +++++++++++++------- imgui_internal.h | 1 - 4 files changed, 117 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c5039d63..7921b1d1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2489,7 +2489,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. -void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) +void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; if (text_end_full == NULL) @@ -2503,15 +2503,42 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, // min max ellipsis_max // <-> this is generally some padding value - // FIXME-STYLE: RenderPixelEllipsis() style should use actual font data. const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; - const int ellipsis_dot_count = 3; - const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f; const char* text_end_ellipsis = NULL; + const ImFontGlyph* glyph; + int ellipsis_char_num = 1; + ImWchar ellipsis_codepoint = font->EllipsisCodePoint; + if (ellipsis_codepoint != (ImWchar)-1) + glyph = font->FindGlyph(ellipsis_codepoint); + else + { + ellipsis_codepoint = (ImWchar)'.'; + glyph = font->FindGlyph(ellipsis_codepoint); + ellipsis_char_num = 3; + } + + float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side + float ellipsis_width = ellipsis_glyph_width; // Full width of entire ellipsis + float push_left = 1.f; + + if (ellipsis_char_num > 1) + { + const float spacing_between_dots = 1.f * (draw_list->_Data->FontSize / font->FontSize); + ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; + // Full ellipsis size without free spacing after it. + ellipsis_width = ellipsis_glyph_width * (float)ellipsis_char_num - spacing_between_dots; + if (glyph->X0 > 1.f) + { + // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). + push_left = 0.f; + } + } + float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { // Always display at least 1 character if there's no room for character + ellipsis @@ -2524,11 +2551,66 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, text_end_ellipsis--; text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } + + if (text_end_ellipsis != text_end_full) + { + // +---- First invisible character we arrived at. + // / +-- Character that we hope to be first invisible. + // [l][i] + // |||| + // \ \__ extra_spacing when two characters got hidden + // \___ extra_spacing when one character got hidden + unsigned c = 0; + float extra_spacing = 0; + const char* text_end_ellipsis_prev = text_end_ellipsis; + text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); + if (c && !ImCharIsBlankW(c)) + { + const ImFontGlyph* hidden_glyph = font->FindGlyph(c); + // Free space after first invisible glyph + extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; + c = 0; + text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); + if (c && !ImCharIsBlankW(c)) + { + hidden_glyph = font->FindGlyph(text_end_ellipsis[1]); + // Space before next invisible glyph. This intentionally ignores space from the first invisible + // glyph as that space will serve as spacing between ellipsis and last visible character. Without + // doing this we may get into awkward situations where ellipsis pretty much sticks to the last + // visible character. This issue manifests with the default font for word "Brocolli" there both i + // and l are very thin. Unfortunately this makes fonts with wider gaps (like monospace) look a bit + // worse, but it is a fair middle ground. + extra_spacing = hidden_glyph->X0; + } + } + + if (extra_spacing > 0) + { + // Repeat calculation hoping that we will get extra character visible + text_width += extra_spacing; + // Text length calculation is essentially an optimized version of this: + // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + // It avoids calculating entire width of the string. + text_size_clipped_x += font->CalcTextSizeA(font_size, text_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; + } + else + text_end_ellipsis = text_end_ellipsis_prev; + } + RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); - const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f; - if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x) - RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count); + // This variable pushes ellipsis to the left from last visible character. This is mostly useful when rendering + // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra + // spacing is not needed. + float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; + if (ellipsis_x + ellipsis_width - push_left <= ellipsis_max_x) + { + for (int i = 0; i < ellipsis_char_num; i++) + { + font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_codepoint); + ellipsis_x += ellipsis_glyph_width; + } + } } else { diff --git a/imgui.h b/imgui.h index 42ee5340..d4a81c3b 100644 --- a/imgui.h +++ b/imgui.h @@ -2011,6 +2011,7 @@ struct ImFontConfig bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + ImWchar EllipsisCodePoint; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) @@ -2192,6 +2193,7 @@ struct ImFont float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) bool DirtyLookupTables; // 1 // out // + ImWchar EllipsisCodePoint; // -1 // out // // Override a codepoint used for ellipsis rendering. // Methods IMGUI_API ImFont(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3eb1067e..b4801c26 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1428,6 +1428,7 @@ ImFontConfig::ImFontConfig() RasterizerMultiply = 1.0f; memset(Name, 0, sizeof(Name)); DstFont = NULL; + EllipsisCodePoint = (ImWchar)-1; } //----------------------------------------------------------------------------- @@ -1618,6 +1619,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } + if (new_font_cfg.DstFont->EllipsisCodePoint == (ImWchar)-1) + new_font_cfg.DstFont->EllipsisCodePoint = font_cfg->EllipsisCodePoint; + // Invalidate texture ClearTexData(); return new_font_cfg.DstFont; @@ -1652,6 +1656,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.SizePixels = 13.0f * 1.0f; if (font_cfg.Name[0] == '\0') ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); + font_cfg.EllipsisCodePoint = (ImWchar)0x0085; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); @@ -2196,6 +2201,26 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) for (int i = 0; i < atlas->Fonts.Size; i++) if (atlas->Fonts[i]->DirtyLookupTables) atlas->Fonts[i]->BuildLookupTable(); + + // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). + // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. + for (int i = 0; i < atlas->Fonts.size(); i++) + { + ImFont* font = atlas->Fonts[i]; + if (font->EllipsisCodePoint == (ImWchar)-1) + { + const ImWchar ellipsis_variants[] = {(ImWchar)0x2026, (ImWchar)0x0085, (ImWchar)0}; + for (int j = 0; ellipsis_variants[j] != (ImWchar) 0; j++) + { + ImWchar ellipsis_codepoint = ellipsis_variants[j]; + if (font->FindGlyph(ellipsis_codepoint) != font->FallbackGlyph) // Verify glyph exists + { + font->EllipsisCodePoint = ellipsis_codepoint; + break; + } + } + } + } } // Retrieve list of range (2 int per range, values are inclusive) @@ -2474,6 +2499,7 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; + EllipsisCodePoint = (ImWchar)-1; } ImFont::~ImFont() @@ -3012,7 +3038,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // - RenderMouseCursor() // - RenderArrowPointingAt() // - RenderRectFilledRangeH() -// - RenderPixelEllipsis() //----------------------------------------------------------------------------- void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor) @@ -3122,18 +3147,6 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im draw_list->PathFillConvex(col); } -// FIXME: Rendering an ellipsis "..." is a surprisingly tricky problem for us... we cannot rely on font glyph having it, -// and regular dot are typically too wide. If we render a dot/shape ourselves it comes with the risk that it wouldn't match -// the boldness or positioning of what the font uses... -void ImGui::RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count) -{ - ImFont* font = draw_list->_Data->Font; - const float font_scale = draw_list->_Data->FontSize / font->FontSize; - pos.y += (float)(int)(font->DisplayOffset.y + font->Ascent * font_scale + 0.5f - 1.0f); - for (int dot_n = 0; dot_n < count; dot_n++) - draw_list->AddRectFilled(ImVec2(pos.x + dot_n * 2.0f, pos.y), ImVec2(pos.x + dot_n * 2.0f + 1.0f, pos.y + 1.0f), col); -} - //----------------------------------------------------------------------------- // [SECTION] Decompression code //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 9c87d2a1..ea8a4099 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1635,7 +1635,6 @@ namespace ImGui IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); - IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while. From 57623c15ddae10a6b0ba6b206d2502e7951dd705 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 10:00:28 +0200 Subject: [PATCH 10/14] Font: Narrow ellipsis: various minor stylistic tweaks (#2775) --- docs/CHANGELOG.txt | 4 +++ docs/TODO.txt | 1 + imgui.cpp | 61 ++++++++++++++++++++-------------------------- imgui.h | 6 ++--- imgui_demo.cpp | 3 ++- imgui_draw.cpp | 29 ++++++++++------------ 6 files changed, 49 insertions(+), 55 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6e487ae5..36ba83ba 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,10 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly + unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. + Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow + as possible. (#2775) [@rokups] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) - Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when diff --git a/docs/TODO.txt b/docs/TODO.txt index 70c64c40..df413b7e 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -275,6 +275,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype) - font: free the Alpha buffer if user only requested RGBA. !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). + - font: for the purpose of RenderTextEllipsis(), it might be useful that CalcTextSizeA() can ignore the trailing padding? - font: a CalcTextHeight() helper could run faster than CalcTextSize().y - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX - font: finish CustomRectRegister() to allow mapping Unicode codepoint to custom texture data diff --git a/imgui.cpp b/imgui.cpp index 7921b1d1..4a606daa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2506,38 +2506,32 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; const char* text_end_ellipsis = NULL; - const ImFontGlyph* glyph; - int ellipsis_char_num = 1; - ImWchar ellipsis_codepoint = font->EllipsisCodePoint; - if (ellipsis_codepoint != (ImWchar)-1) - glyph = font->FindGlyph(ellipsis_codepoint); - else + ImWchar ellipsis_char = font->EllipsisChar; + int ellipsis_char_count = 1; + if (ellipsis_char == (ImWchar)-1) { - ellipsis_codepoint = (ImWchar)'.'; - glyph = font->FindGlyph(ellipsis_codepoint); - ellipsis_char_num = 3; + ellipsis_char = (ImWchar)'.'; + ellipsis_char_count = 3; } + const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char); - float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side - float ellipsis_width = ellipsis_glyph_width; // Full width of entire ellipsis - float push_left = 1.f; + float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side + float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis + float push_left = 1.0f; - if (ellipsis_char_num > 1) + if (ellipsis_char_count > 1) { - const float spacing_between_dots = 1.f * (draw_list->_Data->FontSize / font->FontSize); - ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; // Full ellipsis size without free spacing after it. - ellipsis_width = ellipsis_glyph_width * (float)ellipsis_char_num - spacing_between_dots; - if (glyph->X0 > 1.f) - { - // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). - push_left = 0.f; - } + const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize); + ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; + ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; + if (glyph->X0 > 1.0f) + push_left = 0.0f; // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). } - float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f); - float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; + float text_avail_width = ImMax((pos_max.x - ellipsis_total_width) - pos_min.x, 1.0f); + float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { @@ -2547,7 +2541,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con } while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) { - // Trim trailing space before ellipsis + // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text) text_end_ellipsis--; text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } @@ -2560,16 +2554,15 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con // |||| // \ \__ extra_spacing when two characters got hidden // \___ extra_spacing when one character got hidden - unsigned c = 0; - float extra_spacing = 0; + unsigned int c = 0; + float extra_spacing = 0.0f; const char* text_end_ellipsis_prev = text_end_ellipsis; text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); if (c && !ImCharIsBlankW(c)) { - const ImFontGlyph* hidden_glyph = font->FindGlyph(c); // Free space after first invisible glyph + const ImFontGlyph* hidden_glyph = font->FindGlyph((ImWchar)c); extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; - c = 0; text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); if (c && !ImCharIsBlankW(c)) { @@ -2587,11 +2580,11 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con if (extra_spacing > 0) { // Repeat calculation hoping that we will get extra character visible - text_width += extra_spacing; + text_avail_width += extra_spacing; // Text length calculation is essentially an optimized version of this: // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; // It avoids calculating entire width of the string. - text_size_clipped_x += font->CalcTextSizeA(font_size, text_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; + text_size_clipped_x += font->CalcTextSizeA(font_size, text_avail_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; } else text_end_ellipsis = text_end_ellipsis_prev; @@ -2603,14 +2596,12 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra // spacing is not needed. float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; - if (ellipsis_x + ellipsis_width - push_left <= ellipsis_max_x) - { - for (int i = 0; i < ellipsis_char_num; i++) + if (ellipsis_x + ellipsis_total_width - push_left <= ellipsis_max_x) + for (int i = 0; i < ellipsis_char_count; i++) { - font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_codepoint); + font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); ellipsis_x += ellipsis_glyph_width; } - } } else { diff --git a/imgui.h b/imgui.h index d4a81c3b..9e875f89 100644 --- a/imgui.h +++ b/imgui.h @@ -2011,7 +2011,7 @@ struct ImFontConfig bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. - ImWchar EllipsisCodePoint; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. + ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) @@ -2188,12 +2188,12 @@ struct ImFont ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. - ImWchar FallbackChar; // 2 // in // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() + ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar() + ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) bool DirtyLookupTables; // 1 // out // - ImWchar EllipsisCodePoint; // -1 // out // // Override a codepoint used for ellipsis rendering. // Methods IMGUI_API ImFont(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fd1d85a3..e8e87469 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3283,7 +3283,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SameLine(); HelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); - ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); + ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar); + ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar); const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b4801c26..dd21523e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1426,9 +1426,9 @@ ImFontConfig::ImFontConfig() MergeMode = false; RasterizerFlags = 0x00; RasterizerMultiply = 1.0f; + EllipsisChar = (ImWchar)-1; memset(Name, 0, sizeof(Name)); DstFont = NULL; - EllipsisCodePoint = (ImWchar)-1; } //----------------------------------------------------------------------------- @@ -1619,8 +1619,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } - if (new_font_cfg.DstFont->EllipsisCodePoint == (ImWchar)-1) - new_font_cfg.DstFont->EllipsisCodePoint = font_cfg->EllipsisCodePoint; + if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1) + new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; // Invalidate texture ClearTexData(); @@ -1656,7 +1656,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) font_cfg.SizePixels = 13.0f * 1.0f; if (font_cfg.Name[0] == '\0') ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); - font_cfg.EllipsisCodePoint = (ImWchar)0x0085; + font_cfg.EllipsisChar = (ImWchar)0x0085; const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); @@ -2204,22 +2204,19 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. + // FIXME: Also note that 0x2026 is currently seldomly included in our font ranges. Because of this we are more likely to use three individual dots. for (int i = 0; i < atlas->Fonts.size(); i++) { ImFont* font = atlas->Fonts[i]; - if (font->EllipsisCodePoint == (ImWchar)-1) - { - const ImWchar ellipsis_variants[] = {(ImWchar)0x2026, (ImWchar)0x0085, (ImWchar)0}; - for (int j = 0; ellipsis_variants[j] != (ImWchar) 0; j++) + if (font->EllipsisChar != (ImWchar)-1) + continue; + const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; + for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++) + if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists { - ImWchar ellipsis_codepoint = ellipsis_variants[j]; - if (font->FindGlyph(ellipsis_codepoint) != font->FallbackGlyph) // Verify glyph exists - { - font->EllipsisCodePoint = ellipsis_codepoint; - break; - } + font->EllipsisChar = ellipsis_variants[j]; + break; } - } } } @@ -2490,6 +2487,7 @@ ImFont::ImFont() FontSize = 0.0f; FallbackAdvanceX = 0.0f; FallbackChar = (ImWchar)'?'; + EllipsisChar = (ImWchar)-1; DisplayOffset = ImVec2(0.0f, 0.0f); FallbackGlyph = NULL; ContainerAtlas = NULL; @@ -2499,7 +2497,6 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; - EllipsisCodePoint = (ImWchar)-1; } ImFont::~ImFont() From 1c951dca977e24018110aff7374d7cb3a062e5da Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 11:11:14 +0200 Subject: [PATCH 11/14] Font: Narrow ellipsis: once we know an ellipsis is going to be drawn, we can claim the space between pos_max.x and ellipsis_max.x which gives us enough extra space to not requires the further (and otherwise valid) optimizations. Gets us vastly simplified code, yay. (#2775) --- imgui.cpp | 64 ++++++++----------------------------------------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4a606daa..80e8a280 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2496,6 +2496,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con text_end_full = FindRenderedTextEnd(text); const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); + //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255)); + //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255)); + //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255)); + // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels. if (text_size.x > pos_max.x - pos_min.x) { // Hello wo... @@ -2518,7 +2522,6 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis - float push_left = 1.0f; if (ellipsis_char_count > 1) { @@ -2526,13 +2529,11 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize); ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots; ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots; - if (glyph->X0 > 1.0f) - push_left = 0.0f; // Pushing ellipsis to the left will be accomplished by rendering the dot (X0). } - float text_avail_width = ImMax((pos_max.x - ellipsis_total_width) - pos_min.x, 1.0f); + // We can now claim the space between pos_max.x and ellipsis_max.x + const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; - if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { // Always display at least 1 character if there's no room for character + ellipsis @@ -2546,57 +2547,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } - if (text_end_ellipsis != text_end_full) - { - // +---- First invisible character we arrived at. - // / +-- Character that we hope to be first invisible. - // [l][i] - // |||| - // \ \__ extra_spacing when two characters got hidden - // \___ extra_spacing when one character got hidden - unsigned int c = 0; - float extra_spacing = 0.0f; - const char* text_end_ellipsis_prev = text_end_ellipsis; - text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); - if (c && !ImCharIsBlankW(c)) - { - // Free space after first invisible glyph - const ImFontGlyph* hidden_glyph = font->FindGlyph((ImWchar)c); - extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1; - text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full); - if (c && !ImCharIsBlankW(c)) - { - hidden_glyph = font->FindGlyph(text_end_ellipsis[1]); - // Space before next invisible glyph. This intentionally ignores space from the first invisible - // glyph as that space will serve as spacing between ellipsis and last visible character. Without - // doing this we may get into awkward situations where ellipsis pretty much sticks to the last - // visible character. This issue manifests with the default font for word "Brocolli" there both i - // and l are very thin. Unfortunately this makes fonts with wider gaps (like monospace) look a bit - // worse, but it is a fair middle ground. - extra_spacing = hidden_glyph->X0; - } - } - - if (extra_spacing > 0) - { - // Repeat calculation hoping that we will get extra character visible - text_avail_width += extra_spacing; - // Text length calculation is essentially an optimized version of this: - // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; - // It avoids calculating entire width of the string. - text_size_clipped_x += font->CalcTextSizeA(font_size, text_avail_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x; - } - else - text_end_ellipsis = text_end_ellipsis_prev; - } - + // Render text, render ellipsis RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); - - // This variable pushes ellipsis to the left from last visible character. This is mostly useful when rendering - // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra - // spacing is not needed. - float ellipsis_x = pos_min.x + text_size_clipped_x + push_left; - if (ellipsis_x + ellipsis_total_width - push_left <= ellipsis_max_x) + float ellipsis_x = pos_min.x + text_size_clipped_x; + if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x) for (int i = 0; i < ellipsis_char_count; i++) { font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); From 7d5a17e5e4a36f2cabccfb97e9da4db0983eec56 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 11:33:18 +0200 Subject: [PATCH 12/14] Remove trailing spaces (grep for ' \r?$' in visual studio) --- imconfig.h | 6 +++--- imgui.cpp | 42 +++++++++++++++++++++--------------------- imgui.h | 14 +++++++------- imgui_demo.cpp | 8 ++++---- imgui_draw.cpp | 4 ++-- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 36 ++++++++++++++++++------------------ 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/imconfig.h b/imconfig.h index 22a21db0..45e75ecf 100644 --- a/imconfig.h +++ b/imconfig.h @@ -17,7 +17,7 @@ //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts -//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows +//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) @@ -64,9 +64,9 @@ operator MyVec4() const { return MyVec4(x,y,z,w); } */ -//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. +//---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices). -// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. +// Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. //#define ImDrawIdx unsigned int diff --git a/imgui.cpp b/imgui.cpp index c5039d63..b1d8522c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -575,17 +575,17 @@ CODE Q: Where is the documentation? A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. - Run the examples/ and explore them. - - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - - The demo covers most features of Dear ImGui, so you can read the code and see its output. + - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. + - The demo covers most features of Dear ImGui, so you can read the code and see its output. - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ + - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - - Your programming IDE is your friend, find the type or function declaration to find comments + - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. Q: Which version should I get? - A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe - and recommended to sync to master/latest. The library is fairly stable and regressions tend to be + A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe + and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. You may also peak at the 'docking' branch which includes: - Docking/Merging features (https://github.com/ocornut/imgui/issues/2109) - Multi-viewport features (https://github.com/ocornut/imgui/issues/1542) @@ -597,11 +597,11 @@ CODE for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"? - A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when - when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI - (immediate-mode graphical user interface) was coined before and is being used in variety of other - situations (e.g. Unity uses it own implementation of the IMGUI paradigm). - To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, + A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when + when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI + (immediate-mode graphical user interface) was coined before and is being used in variety of other + situations (e.g. Unity uses it own implementation of the IMGUI paradigm). + To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui". @@ -2488,7 +2488,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. -// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. +// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; @@ -2996,8 +2996,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) { // Navigation processing runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget - // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests - // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests + // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). @@ -4044,7 +4044,7 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d return; } - // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. // May trigger for you if you are using PrimXXX functions incorrectly. IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); @@ -4053,7 +4053,7 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // If this assert triggers because you are drawing lots of stuff manually: - // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. + // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents. // - If you want large meshes with more than 64K vertices, you can either: // (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'. @@ -4062,9 +4062,9 @@ static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* d // (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h. // Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time: // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); - // Your own engine or render API may use different parameters or function calls to specify index sizes. + // Your own engine or render API may use different parameters or function calls to specify index sizes. // 2 and 4 bytes indices are generally supported by most graphics API. - // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching + // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching // the 64K limit to split your draw commands in multiple draw lists. if (sizeof(ImDrawIdx) == 2) IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); @@ -4381,7 +4381,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key) // Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]! bool ImGui::IsKeyDown(int user_key_index) { - if (user_key_index < 0) + if (user_key_index < 0) return false; ImGuiContext& g = *GImGui; IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); @@ -5741,7 +5741,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->OuterRectClipped.ClipWith(host_rect); // Inner rectangle - // Not affected by window border size. Used by: + // Not affected by window border size. Used by: // - InnerClipRect // - ScrollToBringRectIntoView() // - NavUpdatePageUpPageDown() @@ -5819,7 +5819,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) render_decorations_in_parent = true; if (render_decorations_in_parent) window->DrawList = parent_window->DrawList; - + // Handle title bar, scrollbar, resize grips and resize borders const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); diff --git a/imgui.h b/imgui.h index 42ee5340..6118d537 100644 --- a/imgui.h +++ b/imgui.h @@ -328,7 +328,7 @@ namespace ImGui IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, + IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, IMGUI_API void PopItemWidth(); IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. @@ -1764,7 +1764,7 @@ struct ImColor // Draw callbacks for advanced uses. // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, -// you can poke into the draw list for that! Draw callback may be useful for example to: +// you can poke into the draw list for that! Draw callback may be useful for example to: // A) Change your GPU render state, // B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' @@ -1795,7 +1795,7 @@ struct ImDrawCmd ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } }; -// Vertex index +// Vertex index // (to allow large meshes with 16-bits indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end) // (to use 32-bits indices: override with '#define ImDrawIdx unsigned int' in imconfig.h) #ifndef ImDrawIdx @@ -1826,7 +1826,7 @@ struct ImDrawChannel }; // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. -// This is used by the Columns api, so items of each column can be batched together in a same draw call. +// This is used by the Columns api, so items of each column can be batched together in a same draw call. struct ImDrawListSplitter { int _Current; // Current channel number (0) @@ -1867,7 +1867,7 @@ enum ImDrawListFlags_ // Draw command list // This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame, // all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to +// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to // access the current window draw list and draw custom primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. // All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) @@ -2126,9 +2126,9 @@ struct ImFontAtlas // [BETA] Custom Rectangles/Glyphs API //------------------------------------------- - // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. + // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. // After calling Build(), you can query the rectangle position and render your pixels. - // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), + // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // so you can render e.g. custom colorful icons and use them as regular glyphs. // Read misc/fonts/README.txt for more details about using colorful icons. IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fd1d85a3..3a652a16 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -17,7 +17,7 @@ // In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is // essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data // in the same place, to make the demo source code faster to read, faster to write, and smaller in size. -// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be +// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be // reentrant or used in multiple threads. This might be a pattern you will want to use in your code, but most of the real data // you would be editing is likely going to be stored outside your functions. @@ -589,7 +589,7 @@ static void ShowDemoWindowWidgets() { for (int i = 0; i < 5; i++) { - // Use SetNextItemOpen() so set the default state of a node to be open. + // Use SetNextItemOpen() so set the default state of a node to be open. // We could also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! if (i == 0) ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -1109,7 +1109,7 @@ static void ShowDemoWindowWidgets() if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } } - // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, + // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); @@ -2259,7 +2259,7 @@ static void ShowDemoWindowLayout() ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::DragFloat("##csx", &contents_size_x); - ImVec2 p = ImGui::GetCursorScreenPos(); + ImVec2 p = ImGui::GetCursorScreenPos(); ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE); ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE); ImGui::Dummy(ImVec2(0, 10)); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3eb1067e..f3832201 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1202,7 +1202,7 @@ void ImDrawListSplitter::ClearFreeMemory() { for (int i = 0; i < _Channels.Size; i++) { - if (i == _Current) + if (i == _Current) memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again _Channels[i]._CmdBuffer.clear(); _Channels[i]._IdxBuffer.clear(); @@ -1307,7 +1307,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list) void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) { IM_ASSERT(idx >= 0 && idx < _Count); - if (_Current == idx) + if (_Current == idx) return; // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); diff --git a/imgui_internal.h b/imgui_internal.h index 9c87d2a1..ca51e51b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -809,7 +809,7 @@ struct ImGuiNextWindowData void* SizeCallbackUserData; float BgAlphaVal; ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. - + ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } }; @@ -1710,7 +1710,7 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned ch // Debug Tools // Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. -#ifndef IM_DEBUG_BREAK +#ifndef IM_DEBUG_BREAK #if defined(__clang__) #define IM_DEBUG_BREAK() __builtin_debugtrap() #elif defined (_MSC_VER) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba3bac87..f924bbd1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -399,37 +399,37 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // See the series of events below and the corresponding state reported by dear imgui: //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() -// Frame N+0 (mouse is outside bb) - - - - - - -// Frame N+1 (mouse moves inside bb) - true - - - - +// Frame N+0 (mouse is outside bb) - - - - - - +// Frame N+1 (mouse moves inside bb) - true - - - - // Frame N+2 (mouse button is down) - true true true - true -// Frame N+3 (mouse button is down) - true true - - - +// Frame N+3 (mouse button is down) - true true - - - // Frame N+4 (mouse moves outside bb) - - true - - - // Frame N+5 (mouse moves inside bb) - true true - - - -// Frame N+6 (mouse button is released) true true - - true - -// Frame N+7 (mouse button is released) - true - - - - -// Frame N+8 (mouse moves outside bb) - - - - - - +// Frame N+6 (mouse button is released) true true - - true - +// Frame N+7 (mouse button is released) - true - - - - +// Frame N+8 (mouse moves outside bb) - - - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) true true true true - true -// Frame N+3 (mouse button is down) - true true - - - -// Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+3 (mouse button is down) - true true - - - +// Frame N+6 (mouse button is released) - true - - true - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) - true - - - true -// Frame N+3 (mouse button is down) - true - - - - +// Frame N+3 (mouse button is down) - true - - - - // Frame N+6 (mouse button is released) true true - - - - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+0 (mouse button is down) - true - - - true -// Frame N+1 (mouse button is down) - true - - - - +// Frame N+1 (mouse button is down) - true - - - - // Frame N+2 (mouse button is released) - true - - - - -// Frame N+3 (mouse button is released) - true - - - - +// Frame N+3 (mouse button is released) - true - - - - // Frame N+4 (mouse button is down) true true true true - true -// Frame N+5 (mouse button is down) - true true - - - +// Frame N+5 (mouse button is down) - true true - - - // Frame N+6 (mouse button is released) - true - - true - -// Frame N+7 (mouse button is released) - true - - - - +// Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // Note that some combinations are supported, // - PressedOnDragDropHold can generally be associated with any flag. @@ -439,7 +439,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // Repeat+ Repeat+ Repeat+ Repeat+ // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick //------------------------------------------------------------------------------------------------------------------------------------------------- -// Frame N+0 (mouse button is down) - true - true +// Frame N+0 (mouse button is down) - true - true // ... - - - - // Frame N + RepeatDelay true true - true // ... - - - - @@ -5507,7 +5507,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); - // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard + // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) @@ -7291,7 +7291,7 @@ void ImGui::PushColumnsBackground() return; window->DrawList->ChannelsSetCurrent(0); int cmd_size = window->DrawList->CmdBuffer.Size; - PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); + PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); IM_UNUSED(cmd_size); IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd } From 3f986e72d955795ea0306c2b6c1007dc0ad53776 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 12:06:31 +0200 Subject: [PATCH 13/14] Internal: Offset STB_TEXTURE_K_ defines to remove that change from #2541 + sponsors update. --- docs/README.md | 4 ++-- imgui_widgets.cpp | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5a706354..a07acc79 100644 --- a/docs/README.md +++ b/docs/README.md @@ -311,10 +311,10 @@ Ongoing dear imgui development is financially supported by users and private spo - Media Molecule, Mobigame, Aras Pranckevičius, Greggman, DotEmu, Nadeo, Supercell, Runner, Aiden Koss, Kylotonn. **Salty caramel supporters** -- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, Morten Skaaning, Nikhil Deshpande, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford. +- Remedy Entertainment, Recognition Robotics, ikrima, Geoffrey Evans, Mercury Labs, Singularity Demo Group, Lionel Landwerlin, Ron Gilbert, Brandon Townsend, G3DVu, Cort Stratton, drudru, Harfang 3D, Jeff Roberts, Rainway inc, Ondra Voves, Mesh Consultants, Unit 2 Games, Neil Bickford, Bill Six, Graham Manders. **Caramel supporters** -- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. +- Jerome Lanquetot, Daniel Collin, Ctrl Alt Ninja, Neil Henning, Neil Blakey-Milner, Aleksei, NeiloGD, Eric, Game Atelier, Vincent Hamm, Morten Skaaning, Colin Riley, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Josh Faust, Martin Donlon, Codecat, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Jonas Bernemann, Johan Andersson, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Andrew Johnson, Sean Hunter, Jordan Mellow, Nefarius Software Solutions, Laura Wieme, Robert Nix, Mick Honey, Steven Kah Hien Wong, Bartosz Bielecki, Oscar Penas, A M, Liam Moynihan, Artometa, Mark Lee, Dimitri Diakopoulos, Pete Goodwin, Johnathan Roatch, nyu lea, Oswald Hurlem, Semyon Smelyanskiy, Le Bach, Jeong MyeongSoo, Chris Matthews, Astrofra, Frederik De Bleser, Anticrisis. And all other past and present supporters; THANK YOU! (Please contact me if you would like to be added or removed from this list) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f924bbd1..3cd0638b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3222,21 +3222,21 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im } // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) -#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left -#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right -#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up -#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down -#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line -#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line -#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text -#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text -#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor -#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor -#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo -#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo -#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word -#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word -#define STB_TEXTEDIT_K_SHIFT 0x20000 +#define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left +#define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right +#define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up +#define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down +#define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line +#define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line +#define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text +#define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text +#define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor +#define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor +#define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo +#define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo +#define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word +#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word +#define STB_TEXTEDIT_K_SHIFT 0x400000 #define STB_TEXTEDIT_IMPLEMENTATION #include "imstb_textedit.h" From b48dc067ae794cd9159397b338a985c0b906404d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 17 Sep 2019 16:16:38 +0200 Subject: [PATCH 14/14] Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) + Fix #2775 --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- imgui.h | 2 +- imgui_demo.cpp | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36ba83ba..0c3a28d6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Other Changes: - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value. - DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat] +- Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) - Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow diff --git a/imgui.cpp b/imgui.cpp index c4b3425d..d717fb17 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3692,7 +3692,7 @@ static void NewFrameSanityChecks() IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!"); IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); - IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); + IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); @@ -5314,7 +5314,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl ImGuiWindowFlags flags = window->Flags; const bool has_close_button = (p_open != NULL); - const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse); + const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; diff --git a/imgui.h b/imgui.h index 965e81a0..a3faa620 100644 --- a/imgui.h +++ b/imgui.h @@ -1289,7 +1289,7 @@ struct ImGuiStyle float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints(). ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. - ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left. + ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left. float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e7ffdddd..13877cd5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3195,7 +3195,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::Text("Alignment"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); - ImGui::Combo("WindowMenuButtonPosition", (int*)&style.WindowMenuButtonPosition, "Left\0Right\0"); + int window_menu_button_position = style.WindowMenuButtonPosition + 1; + if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0")) + style.WindowMenuButtonPosition = window_menu_button_position - 1; ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content."); @@ -3284,7 +3286,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar); + ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar); const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)