From f6d6880a61c3a3139fabcb63541b0339f8fa432b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Jan 2020 20:34:26 +0100 Subject: [PATCH 01/17] Internals: Nav: PushFocusScope, PopFocusScope, GetFocusScopeID() helpers --- imgui.cpp | 16 ++++++++++++++++ imgui_internal.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index c7e7a3c6..50cdf4ee 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6909,6 +6909,22 @@ void ImGui::ActivateItem(ImGuiID id) g.NavNextActivateId = id; } +void ImGui::PushFocusScope(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent); + window->DC.NavFocusScopeIdCurrent = id; +} + +void ImGui::PopFocusScope() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + window->DC.NavFocusScopeIdCurrent = window->IDStack.back(); + window->IDStack.pop_back(); +} + void ImGui::SetKeyboardFocusHere(int offset) { IM_ASSERT(offset >= -1); // -1 is allowed but not below diff --git a/imgui_internal.h b/imgui_internal.h index 894519b2..a19c1811 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1703,6 +1703,11 @@ namespace ImGui IMGUI_API void SetNavID(ImGuiID id, int nav_layer, int focus_scope_id); IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel); + // Focus scope (WIP) + IMGUI_API void PushFocusScope(ImGuiID id); // Note: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there. + IMGUI_API void PopFocusScope(); + inline ImGuiID GetFocusScopeID() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } + // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } From 9ad4c5da7e2806f47fb08cbfa050b1ed3e768fbe Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 15 Jan 2020 17:23:05 +0100 Subject: [PATCH 02/17] Fix zealous warnings + Internals: Renamed members from XxxxID to XxxxxId to be more consistent with rest of the codebase (still some inconsistency left that are harder to fix) --- imgui.cpp | 14 +++++++------- imgui.h | 2 +- imgui_demo.cpp | 5 +++-- imgui_internal.h | 10 +++++----- imgui_widgets.cpp | 4 ++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 50cdf4ee..a9e2dd7a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2753,7 +2753,7 @@ void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) } // FIXME-NAV: Refactor those functions into a single, more explicit one. -void ImGui::SetNavID(ImGuiID id, int nav_layer, int focus_scope_id) +void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow); @@ -2763,7 +2763,7 @@ void ImGui::SetNavID(ImGuiID id, int nav_layer, int focus_scope_id) g.NavWindow->NavLastIds[nav_layer] = id; } -void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel) +void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; SetNavID(id, nav_layer, focus_scope_id); @@ -2958,10 +2958,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() #ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX - if (id == g.DebugItemPickerBreakID) + if (id == g.DebugItemPickerBreakId) { IM_DEBUG_BREAK(); - g.DebugItemPickerBreakID = 0; + g.DebugItemPickerBreakId = 0; } #endif } @@ -3060,7 +3060,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd(). if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); - if (g.DebugItemPickerBreakID == id) + if (g.DebugItemPickerBreakId == id) IM_DEBUG_BREAK(); return true; @@ -3840,7 +3840,7 @@ void ImGui::NewFrame() void ImGui::UpdateDebugToolItemPicker() { ImGuiContext& g = *GImGui; - g.DebugItemPickerBreakID = 0; + g.DebugItemPickerBreakId = 0; if (g.DebugItemPickerActive) { const ImGuiID hovered_id = g.HoveredIdPreviousFrame; @@ -3849,7 +3849,7 @@ void ImGui::UpdateDebugToolItemPicker() g.DebugItemPickerActive = false; if (ImGui::IsMouseClicked(0) && hovered_id) { - g.DebugItemPickerBreakID = hovered_id; + g.DebugItemPickerBreakId = hovered_id; g.DebugItemPickerActive = false; } ImGui::SetNextWindowBgAlpha(0.60f); diff --git a/imgui.h b/imgui.h index 57d0511c..c2cde0d2 100644 --- a/imgui.h +++ b/imgui.h @@ -2228,10 +2228,10 @@ struct ImFont 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 character if a glyph isn't found. Only set via SetFallbackChar() ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering. + bool DirtyLookupTables; // 1 // out // 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 // // Methods IMGUI_API ImFont(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5ccebef2..8e9137e7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3431,8 +3431,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (const ImFontConfig* cfg = &font->ConfigData[config_i]) - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); + if (font->ConfigData) + if (const ImFontConfig* cfg = &font->ConfigData[config_i]) + ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { // Display all glyphs of the fonts in separate pages of 256 characters diff --git a/imgui_internal.h b/imgui_internal.h index a19c1811..ea5accfc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -430,7 +430,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_Disabled = 1 << 10, // disable interactions ImGuiButtonFlags_AlignTextBaseLine = 1 << 11, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 12, // disable mouse interaction if a key modifier is held - ImGuiButtonFlags_NoHoldingActiveID = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_NoHoldingActiveId = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoNavFocus = 1 << 14, // don't override navigation focus when activated ImGuiButtonFlags_NoHoveredOnNav = 1 << 15, // don't report as hovered when navigated on ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold @@ -1160,7 +1160,7 @@ struct ImGuiContext // Debug Tools bool DebugItemPickerActive; - ImGuiID DebugItemPickerBreakID; // Will call IM_DEBUG_BREAK() when encountering this id + ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. @@ -1289,7 +1289,7 @@ struct ImGuiContext LogDepthToExpand = LogDepthToExpandDefault = 2; DebugItemPickerActive = false; - DebugItemPickerBreakID = 0; + DebugItemPickerBreakId = 0; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; @@ -1700,8 +1700,8 @@ namespace ImGui IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. - IMGUI_API void SetNavID(ImGuiID id, int nav_layer, int focus_scope_id); - IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, int focus_scope_id, const ImRect& rect_rel); + IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id); + IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); // Focus scope (WIP) IMGUI_API void PushFocusScope(ImGuiID id); // Note: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 95483e2f..cf437c7e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -517,7 +517,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; - if (flags & ImGuiButtonFlags_NoHoldingActiveID) + if (flags & ImGuiButtonFlags_NoHoldingActiveId) ClearActiveID(); else SetActiveID(id, window); // Hold on ID @@ -5580,7 +5580,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveID; } + if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } if (flags & ImGuiSelectableFlags_PressedOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_PressedOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } From aa34681652c557ce7cbeb6b9e9067d7af3062454 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 17 Jan 2020 11:36:56 +0100 Subject: [PATCH 03/17] Backends: GLFW: inhibit error callback when creating cursors because X11 setups may be missing them + comment (#2980) --- examples/imgui_impl_glfw.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 142b6409..2182efb8 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. // 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). // 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. @@ -175,6 +176,11 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window); #endif + // Create mouse cursors + // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist, + // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. + // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.) + GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL); g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); @@ -191,6 +197,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); #endif + glfwSetErrorCallback(prev_error_callback); // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. g_PrevUserCallbackMousebutton = NULL; From 6c00d1916e854d6605dd4474a188ad3393117504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Sun, 29 Dec 2019 15:39:49 +0100 Subject: [PATCH 04/17] Disable format checks when using stb_sprintf.h STB sprintf allows extra formats like %b or %$d. If ImGui is configured to use STB sprintf, it generates warnings with GCC and clang when using such formats because it keeps applying default printf-style warnings. This commit disables printf-style warnings when using STB sprintf. Since the printf-style warnings are defined in imgui.h based on the compiler, IMGUI_USE_STB_SPRINTF can't just be defined in the cpp file anymore and it's been moved as a proper config in imconfig.h. --- docs/CHANGELOG.txt | 2 ++ imconfig.h | 4 ++++ imgui.cpp | 1 - imgui.h | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ae128853..11e4fdf0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,8 @@ Other Changes: we will rework the circle rendering functions to use textures and automatic segment count selection, those new api can fill a gap. [@ShironekoBen] - Misc: Added ImGuiMouseCursor_NotAllowed enum so it can be used by more shared widgets. [@rokups] +- Misc: Disable format checks when using stb_printf, to allow using extra formats. + Made IMGUI_USE_STB_SPRINTF a properly documented imconfig.h flag. (#2954) [@loicmolinari] - Misc: Added misc/single_file/imgui_single_file.h, We use this to validate compiling all *.cpp files in a same compilation unit. Actual users of that technique (also called "Unity builds") can generally provide this themselves, so we don't really recommend you use this. [@rokups] diff --git a/imconfig.h b/imconfig.h index c4f7891e..6724e40f 100644 --- a/imconfig.h +++ b/imconfig.h @@ -53,6 +53,10 @@ //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION +//---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library. +// Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. +// #define IMGUI_USE_STB_SPRINTF + //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. /* diff --git a/imgui.cpp b/imgui.cpp index a9e2dd7a..09a315cc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1354,7 +1354,6 @@ const char* ImStrSkipBlank(const char* str) // You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are // designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) -//#define IMGUI_USE_STB_SPRINTF #ifdef IMGUI_USE_STB_SPRINTF #define STB_SPRINTF_IMPLEMENTATION #include "stb_sprintf.h" diff --git a/imgui.h b/imgui.h index c2cde0d2..1245ab1b 100644 --- a/imgui.h +++ b/imgui.h @@ -76,7 +76,7 @@ Index of this file: #include #define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #endif -#if defined(__clang__) || defined(__GNUC__) +#if !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__)) #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // To apply printf-style warnings to our functions. #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else From 2478dbfdb7a3b5d10738f16128e5a7afd5d429e1 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 17 Jan 2020 14:18:16 +0100 Subject: [PATCH 05/17] Disable warning C5054 introduced in VS 2019 16.2 (#2983) --- imgui.cpp | 3 +++ imgui_widgets.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 09a315cc..6ef20da8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -812,6 +812,9 @@ CODE #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later +#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types +#endif #endif // Clang/GCC warnings with -Weverything diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cf437c7e..124594db 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -47,8 +47,11 @@ Index of this file: // Visual Studio warnings #ifdef _MSC_VER -#pragma warning (disable: 4127) // condition expression is constant -#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#pragma warning (disable: 4127) // condition expression is constant +#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen +#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later +#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types +#endif #endif // Clang/GCC warnings with -Weverything From e499497ec547616e70c0cfdd59f3a1c681d503e2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 17 Jan 2020 14:56:56 +0100 Subject: [PATCH 06/17] Backends: Win32: Added support for io.KeySuper (Windows key) for consistency with other backends. (#2976) Even if realistically it is difficult to make good use of under Windows. + Style editor: Use a more explicit form of RadioButton() to avoid being depending on underlying flags type. (#2983) --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_win32.cpp | 3 ++- imgui_demo.cpp | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 11e4fdf0..a3e03316 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -88,6 +88,8 @@ Other Changes: XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput, the later may be problematic if compiling with recent Windows SDK and you want your app to run on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716) +- Backends: Win32: Added support for io.KeySuper (Windows key) for consistency with other backends, + even if realistically it is difficult to make good use of under Windows. - CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 140e1e4b..189f6d3b 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -28,6 +28,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-01-17: Inputs: Added support for io.KeySuper (Windows key) for consistency with other backends, even if realistically it is difficult to make good use of under Windows. // 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). @@ -229,7 +230,7 @@ void ImGui_ImplWin32_NewFrame() io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; - io.KeySuper = false; + io.KeySuper = ((::GetKeyState(VK_LWIN) | ::GetKeyState(VK_RWIN)) & 0x8000) != 0; // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. // Update OS mouse position diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8e9137e7..ec8c142f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3374,9 +3374,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) filter.Draw("Filter colors", ImGui::GetFontSize() * 16); static ImGuiColorEditFlags alpha_flags = 0; - ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine(); - ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine(); - ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::SameLine(); + if (ImGui::RadioButton("Opaque", alpha_flags == 0)) { alpha_flags = 0; } ImGui::SameLine(); + if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine(); + if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); HelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu."); ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); From 8bcac7d95caa7e3b960b7bf7c3bcda4ecfe4541f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 17 Jan 2020 15:18:33 +0100 Subject: [PATCH 07/17] Backends: GLFW, SDL: report Windows key (io.KeySuper) as always released. Neither GLFW nor SDL can correctly report the key release in every cases (e.g. when using Win+V) causing problems with some widgets. The next release of GLFW (3.4+) will have a fix for it. However since it is both difficult and discouraged to make use of this key for Windows application anyway, we just hide it. (#2976) --- docs/CHANGELOG.txt | 6 ++++-- examples/imgui_impl_glfw.cpp | 4 ++++ examples/imgui_impl_sdl.cpp | 4 ++++ examples/imgui_impl_win32.cpp | 3 +-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a3e03316..11afd5e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -84,12 +84,14 @@ Other Changes: - Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups] - Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available on Wayland). (#2800, #2802) [@NeroBurner] +- Backends: GLFW, SDL: report Windows key (io.KeySuper) as always released. Neither GLFW nor SDL can + correctly report the key release in every cases (e.g. when using Win+V) causing problems with some + widgets. The next release of GLFW (3.4+) will have a fix for it. However since it is both difficult + and discouraged to make use of this key for Windows application anyway, we just hide it. (#2976) - Backends: Win32: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD to disable all XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput, the later may be problematic if compiling with recent Windows SDK and you want your app to run on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716) -- Backends: Win32: Added support for io.KeySuper (Windows key) for consistency with other backends, - even if realistically it is difficult to make good use of under Windows. - CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 2182efb8..c496232c 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -122,7 +122,11 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; +#ifdef _WIN32 + io.KeySuper = false; +#else io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +#endif } void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) diff --git a/examples/imgui_impl_sdl.cpp b/examples/imgui_impl_sdl.cpp index 8a295aaa..32722bf6 100644 --- a/examples/imgui_impl_sdl.cpp +++ b/examples/imgui_impl_sdl.cpp @@ -115,7 +115,11 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); +#ifdef _WIN32 + io.KeySuper = false; +#else io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); +#endif return true; } } diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 189f6d3b..140e1e4b 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -28,7 +28,6 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2020-01-17: Inputs: Added support for io.KeySuper (Windows key) for consistency with other backends, even if realistically it is difficult to make good use of under Windows. // 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). @@ -230,7 +229,7 @@ void ImGui_ImplWin32_NewFrame() io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; - io.KeySuper = ((::GetKeyState(VK_LWIN) | ::GetKeyState(VK_RWIN)) & 0x8000) != 0; + io.KeySuper = false; // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. // Update OS mouse position From 15c6abe4bea4da14900fe53fa13ea2eb9133df32 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 20 Jan 2020 11:48:17 +0100 Subject: [PATCH 08/17] Internals: Standard math functions default redirection uses a define instead of an extraneous inline function call --- imgui_internal.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index ea5accfc..80453c95 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -297,22 +297,21 @@ IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* // Helpers: Maths // - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy) #ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS -static inline float ImFabs(float x) { return fabsf(x); } -static inline float ImSqrt(float x) { return sqrtf(x); } -static inline float ImPow(float x, float y) { return powf(x, y); } -static inline double ImPow(double x, double y) { return pow(x, y); } -static inline float ImFmod(float x, float y) { return fmodf(x, y); } -static inline double ImFmod(double x, double y) { return fmod(x, y); } -static inline float ImCos(float x) { return cosf(x); } -static inline float ImSin(float x) { return sinf(x); } -static inline float ImAcos(float x) { return acosf(x); } -static inline float ImAtan2(float y, float x) { return atan2f(y, x); } -static inline double ImAtof(const char* s) { return atof(s); } -static inline float ImFloorStd(float x) { return floorf(x); } // we already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by stb_truetype) -static inline float ImCeil(float x) { return ceilf(x); } +#define ImFabs(X) fabsf(X) +#define ImSqrt(X) sqrtf(X) +#define ImFmod(X, Y) fmodf((X), (Y)) +#define ImCos(X) cosf(X) +#define ImSin(X) sinf(X) +#define ImAcos(X) acosf(X) +#define ImAtan2(Y, X) atan2f((Y), (X)) +#define ImAtof(STR) atof(STR) +#define ImFloorStd(X) floorf(X) // We already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by e.g. stb_truetype) +#define ImCeil(X) ceilf(X) +static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision +static inline double ImPow(double x, double y) { return pow(x, y); } #endif -// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support for variety of types: signed/unsigned int/long long float/double -// (Exceptionally using templates here but we could also redefine them for variety of types) +// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double +// (Exceptionally using templates here but we could also redefine them for those types) template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } From 0a3df4b2cebfdd3ead550e51718d90565feaf64c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 20 Jan 2020 14:28:01 +0100 Subject: [PATCH 09/17] Update FAQ.md --- docs/FAQ.md | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 3216a524..571c94c7 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -54,6 +54,8 @@ or view this file with any Markdown viewer. - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. - The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts. +##### [Return to Index](#index) + --- ### Q. What is this library called? @@ -62,6 +64,8 @@ or view this file with any Markdown viewer. (The library misleadingly started its life in 2014 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 in December 2015 a fully qualified name "Dear ImGui" for this library. +##### [Return to Index](#index) + --- ### Q: Which version should I get? @@ -73,10 +77,9 @@ You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch Many projects are using this branch and it is kept in sync with master regularly. ---- - ##### [Return to Index](#index) +---- # Q&A: Integration @@ -97,6 +100,8 @@ e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` **Note:** Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) +##### [Return to Index](#index) + --- ### Q: How can I enable keyboard or gamepad controls? @@ -106,6 +111,8 @@ e.g. `if (ImGui::GetIO().WantCaptureMouse) { ... }` - See [Control Sheets for Gamepads](http://www.dearimgui.org/controls_sheets) (reference PNG/PSD for for PS4, XB1, Switch gamepads). - See `USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for more details. +##### [Return to Index](#index) + --- ### Q: How can I use this on a machine without mouse, keyboard or screen? (input share, remote display) @@ -117,9 +124,9 @@ to your host computer, based on the Synergy 1.x protocol. Make sure you download Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols. - Game console users: consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui) or [imgui-ws](https://github.com/ggerganov/imgui-ws) which sends the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. See [Wiki](https://github.com/ocornut/imgui/wiki) index for most details. -- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate -for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing -for screen real-estate and precision. +- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing for screen real-estate and precision. + +##### [Return to Index](#index) --- @@ -127,6 +134,8 @@ for screen real-estate and precision. In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. +##### [Return to Index](#index) + --- ### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. @@ -138,6 +147,7 @@ and **NOT** as ##### [Return to Index](#index) +--- # Q&A: Usage @@ -257,6 +267,8 @@ will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. See what makes more sense in your situation! +##### [Return to Index](#index) + --- ### Q: How can I display an image? What is ImTextureID, how does it work? @@ -337,6 +349,8 @@ my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a I ``` Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated. +##### [Return to Index](#index) + --- ### Q: How can I use my own math types instead of ImVec2/ImVec4? @@ -344,6 +358,8 @@ Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understa You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the `IM_VEC2_CLASS_EXTRA`/`IM_VEC4_CLASS_EXTRA` macros to add implicit type conversions. This way you'll be able to use your own types everywhere, e.g. passing `MyVector2` or `glm::vec2` to ImGui functions instead of `ImVec2`. +##### [Return to Index](#index) + --- ### Q: How can I interact with standard C++ types (such as std::string and std::vector)? @@ -366,6 +382,8 @@ One possible implementation of a helper to facilitate printf-style building of s This is a small helper where you can instance strings with configurable local buffers length. Many game engines will provide similar or better string helpers. +##### [Return to Index](#index) + --- ### Q: How can I display custom shapes? (using low-level ImDrawList API) @@ -402,6 +420,7 @@ ImGui::End(); ##### [Return to Index](#index) +--- # Q&A: Fonts, Text @@ -429,6 +448,8 @@ io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT ``` +##### [Return to Index](#index) + --- ### Q: How can I easily use icons in my application? @@ -439,6 +460,8 @@ You may want to see `ImFontConfig::GlyphMinAdvanceX` to make your icon look mono With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas, and copying your own graphics data into it. See docs/FONTS.txt about using the AddCustomRectFontGlyph API. +##### [Return to Index](#index) + --- ### Q: How can I load multiple fonts? @@ -471,6 +494,8 @@ io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs ``` +##### [Return to Index](#index) + --- ### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? @@ -504,6 +529,7 @@ the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft ##### [Return to Index](#index) +--- # Q&A: Concerns @@ -515,6 +541,10 @@ You may take a look at: - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Gallery](https://github.com/ocornut/imgui/issues/2847) +##### [Return to Index](#index) + +--- + ### Q: Can you create elaborate/serious tools with Dear ImGui? Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. @@ -523,6 +553,10 @@ Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm. +##### [Return to Index](#index) + +--- + ### Q: Can you reskin the look of Dear ImGui? Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it. @@ -530,6 +564,10 @@ Somehow. You can alter the look of the interface to some degree: changing colors A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119)) ![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png) +##### [Return to Index](#index) + +--- + ### Q: Why using C++ (as opposed to C)? Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. @@ -538,6 +576,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci ##### [Return to Index](#index) +--- # Q&A: Community From 3fe6ae97323ddfa9cce73831b930af63c34d287b Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 20 Jan 2020 18:09:59 +0100 Subject: [PATCH 10/17] Internals: Move some Nav functions and members around (no functional change) + Misc comments --- docs/README.md | 6 +- examples/README.txt | 2 +- examples/example_glut_opengl2/main.cpp | 2 +- examples/imgui_impl_glut.cpp | 2 +- examples/imgui_impl_glut.h | 2 +- imgui.cpp | 116 ++++++++++++------------- imgui.h | 2 +- imgui_internal.h | 22 ++--- 8 files changed, 78 insertions(+), 76 deletions(-) diff --git a/docs/README.md b/docs/README.md index 97b7812c..2bad5cae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -114,19 +114,19 @@ Officially maintained bindings (in repository): Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): - Languages: C, C#/.Net, ChaiScript, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/GameMakerStudio2, Irrlicht, Ogre, OpenFrameworks, OpenSceneGraph/OSG, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Irrlicht, Ogre, OpenFrameworks, OSG/OpenSceneGraph, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. ### Upcoming Changes -Some of the goals for 2019-2020 are: +Some of the goals for 2020 are: - Finish work on docking, tabs. (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on multiple viewports / multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback) - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) +- Finish work on new Tables API (to replace Columns). (see [#2957](https://github.com/ocornut/imgui/issues/2957)) - Add an automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435)) -- Make Columns better. They are currently pretty terrible! New Tables API coming Q4 2019! - Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware. ### Gallery diff --git a/examples/README.txt b/examples/README.txt index a2655da6..da05b056 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -106,7 +106,7 @@ List of Platforms Bindings in this repository: imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl back-ends) imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_win32.cpp ; Win32 native API (Windows) - imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2019) + imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2020!) List of Renderer Bindings in this repository: diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index 34c26dbe..03db3fce 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -2,7 +2,7 @@ // If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp. // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! #include "imgui.h" diff --git a/examples/imgui_impl_glut.cpp b/examples/imgui_impl_glut.cpp index 56d8c553..fe519d9c 100644 --- a/examples/imgui_impl_glut.cpp +++ b/examples/imgui_impl_glut.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. OpenGL2) // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: diff --git a/examples/imgui_impl_glut.h b/examples/imgui_impl_glut.h index 506c3867..0c561207 100644 --- a/examples/imgui_impl_glut.h +++ b/examples/imgui_impl_glut.h @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. OpenGL2) // !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2019, you are being abused. Please show some resistance. !!! +// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: diff --git a/imgui.cpp b/imgui.cpp index 6ef20da8..bb94bddf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2754,27 +2754,6 @@ void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; } -// FIXME-NAV: Refactor those functions into a single, more explicit one. -void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindow); - IM_ASSERT(nav_layer == 0 || nav_layer == 1); - g.NavId = id; - g.NavFocusScopeId = focus_scope_id; - g.NavWindow->NavLastIds[nav_layer] = id; -} - -void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - SetNavID(id, nav_layer, focus_scope_id); - g.NavWindow->NavRectRel[nav_layer] = rect_rel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; -} - void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -2807,31 +2786,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdUsingKeyInputMask = 0x00; } -// FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring. -void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(id != 0); - - // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. - // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) - const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; - if (g.NavWindow != window) - g.NavInitRequest = false; - g.NavWindow = window; - g.NavId = id; - g.NavLayer = nav_layer; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; - window->NavLastIds[nav_layer] = id; - if (window->DC.LastItemId == id) - window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); - - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; -} - void ImGui::ClearActiveID() { SetActiveID(0, NULL); @@ -2879,18 +2833,18 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla // An active popup disable hovering on other windows (apart from its own children) // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; - if (g.NavWindow) - if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) - if (focused_root_window->WasActive && focused_root_window != window->RootWindow) - { - // For the purpose of those flags we differentiate "standard popup" from "modal popup" - // NB: The order of those two tests is important because Modal windows are also Popups. - if (focused_root_window->Flags & ImGuiWindowFlags_Modal) - return false; - if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - return false; - } - + if (!g.NavWindow) + return false; + if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) + if (focused_root_window->WasActive && focused_root_window != window->RootWindow) + { + // For the purpose of those flags we differentiate "standard popup" from "modal popup" + // NB: The order of those two tests is important because Modal windows are also Popups. + if (focused_root_window->Flags & ImGuiWindowFlags_Modal) + return false; + if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + return false; + } return true; } @@ -7860,6 +7814,52 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- +// FIXME-NAV: The existance of SetNavID vs SetNavIDWithRectRel vs SetFocusID is incredibly messy and confusing, +// and needs some explanation or serious refactoring. +void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); + g.NavId = id; + g.NavFocusScopeId = focus_scope_id; + g.NavWindow->NavLastIds[nav_layer] = id; +} + +void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavID(id, nav_layer, focus_scope_id); + g.NavWindow->NavRectRel[nav_layer] = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + +void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(id != 0); + + // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. + // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) + const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; + if (g.NavWindow != window) + g.NavInitRequest = false; + g.NavWindow = window; + g.NavId = id; + g.NavLayer = nav_layer; + g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; + window->NavLastIds[nav_layer] = id; + if (window->DC.LastItemId == id) + window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); + + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; +} + ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy) { if (ImFabs(dx) > ImFabs(dy)) diff --git a/imgui.h b/imgui.h index 1245ab1b..32468168 100644 --- a/imgui.h +++ b/imgui.h @@ -595,7 +595,7 @@ namespace ImGui // - You can also use SameLine(pos_x) to mimic simplified columns. // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) // - There is a maximum of 64 columns. - // - By end of the 2019 we will expose a new 'Table' api which will replace columns. + // - Currently working on new 'Tables' api which will replace columns (see GitHub #2957) IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index diff --git a/imgui_internal.h b/imgui_internal.h index 80453c95..e9c39d8e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1046,17 +1046,10 @@ struct ImGuiContext ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). - ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging - ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed top-most. - ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f - ImGuiWindow* NavWindowingList; - float NavWindowingTimer; - float NavWindowingHighlightAlpha; - bool NavWindowingToggleLayer; ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid @@ -1078,6 +1071,14 @@ struct ImGuiContext 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) + // Navigation: Windowing (CTRL+TAB, holding Menu button + directional pads to move/resize) + ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed top-most. + ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f + ImGuiWindow* NavWindowingList; + float NavWindowingTimer; + float NavWindowingHighlightAlpha; + bool NavWindowingToggleLayer; + // Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) ImGuiWindow* FocusRequestCurrWindow; // ImGuiWindow* FocusRequestNextWindow; // @@ -1221,9 +1222,6 @@ struct ImGuiContext NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; - NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; - NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; - NavWindowingToggleLayer = false; NavLayer = ImGuiNavLayer_Main; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; @@ -1240,6 +1238,10 @@ struct ImGuiContext NavMoveRequestForward = ImGuiNavForward_None; NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None; + NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL; + NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; + NavWindowingToggleLayer = false; + FocusRequestCurrWindow = FocusRequestNextWindow = NULL; FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX; FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX; From 7a22767483c4c6d0ea4d782c0bca4dbe0fc94776 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Mon, 20 Jan 2020 15:57:39 +0200 Subject: [PATCH 11/17] CI: Add MSVC extra warnings build and correct labels of other extra warnings builds. --- .github/workflows/build.yml | 11 +++++++++-- examples/example_null/build_win32.bat | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04f8f6dc..a874bfff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ jobs: Windows: runs-on: windows-2019 env: + VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\ MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\ # Until gh-actions allow us to use env variables inside other env variables (because we need %GITHUB_WORKSPACE%) we have to use relative path to imgui/examples/example_name directory. SDL2_DIR: ..\..\SDL2-devel-2.0.10-VC\SDL2-2.0.10\ @@ -41,9 +42,15 @@ jobs: } # Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long. - - name: Build example_null (extra warnings) + - name: Build example_null (extra warnings, mingw 64-bit) run: mingw32-make -C examples/example_null EXTRA_WARNINGS=1 + - name: Build example_null (extra warnings, msvc 64-bit) + shell: cmd + run: | + cd examples\example_null + "%VS_PATH%\VC\Auxiliary\Build\vcvarsall.bat" x64 && .\build_win32.bat /W4 + - name: Build example_null (single file build) shell: bash run: | @@ -214,7 +221,7 @@ jobs: brew install glfw3 brew install sdl2 - - name: Build example_null (extra warnings) + - name: Build example_null (extra warnings, clang 64-bit) run: make -C examples/example_null EXTRA_WARNINGS=1 - name: Build example_null (single file build) diff --git a/examples/example_null/build_win32.bat b/examples/example_null/build_win32.bat index 12cb70ab..38e79148 100644 --- a/examples/example_null/build_win32.bat +++ b/examples/example_null/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib +cl /nologo /Zi /MD /I ..\.. %* *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib From 2eda3585e7a46fbdb97db6bcd232bde7ecd19fd6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 22 Jan 2020 14:20:56 +0100 Subject: [PATCH 12/17] Fixed hoverable/focus bug introduced in 3fe6ae97 (#2997) + ArrowButtonEx() internal bits. --- imgui.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bb94bddf..86bbd146 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2834,7 +2834,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFla // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; if (!g.NavWindow) - return false; + return true; if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) if (focused_root_window->WasActive && focused_root_window != window->RootWindow) { diff --git a/imgui_internal.h b/imgui_internal.h index e9c39d8e..5065255c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1780,7 +1780,7 @@ namespace ImGui IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos); IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos); - IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags); + IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API void Scrollbar(ImGuiAxis axis); IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners); IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 124594db..dc9b0530 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -720,7 +720,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) { float sz = GetFrameHeight(); - return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0); + return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None); } // Button to close a window From 051ce0765ef8569729c9ae9b3d466132f9010b89 Mon Sep 17 00:00:00 2001 From: Ben Carter Date: Mon, 9 Dec 2019 15:57:24 +0900 Subject: [PATCH 13/17] AddCircle, AddCircleFilled: Add auto-calculation of circle segment counts --- imgui.cpp | 7 +++++++ imgui.h | 9 +++++---- imgui_demo.cpp | 5 +++-- imgui_draw.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- imgui_internal.h | 8 ++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 86bbd146..75b95ba5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -988,6 +988,7 @@ ImGuiStyle::ImGuiStyle() AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + CircleSegmentMaxError = 0.75f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. // Default theme ImGui::StyleColorsDark(this); @@ -3560,6 +3561,7 @@ static void NewFrameSanityChecks() IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); + IM_ASSERT(g.Style.CircleSegmentMaxError > 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_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); @@ -3622,6 +3624,7 @@ void ImGui::NewFrame() IM_ASSERT(g.Font->IsLoaded()); g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; + g.DrawListSharedData.CircleSegmentMaxError = g.Style.CircleSegmentMaxError; g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; if (g.Style.AntiAliasedLines) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; @@ -3630,6 +3633,10 @@ void ImGui::NewFrame() if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; + // Recalculate circle segment counts if the segment error has changed + if (g.DrawListSharedData.CircleSegmentMaxError != g.DrawListSharedData.CircleSegmentCountsMaxCircleSegmentError) + g.DrawListSharedData.RecalculateCircleSegmentCounts(); + g.BackgroundDrawList.Clear(); g.BackgroundDrawList.PushTextureID(g.IO.Fonts->TexID); g.BackgroundDrawList.PushClipRectFullScreen(); diff --git a/imgui.h b/imgui.h index 32468168..7582aafc 100644 --- a/imgui.h +++ b/imgui.h @@ -1359,6 +1359,7 @@ struct ImGuiStyle bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + float CircleSegmentMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. ImVec4 Colors[ImGuiCol_COUNT]; IMGUI_API ImGuiStyle(); @@ -1948,10 +1949,10 @@ struct ImDrawList IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col); IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f); IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); - IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); - IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); - IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); + IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); // Draw a circle - use num_segments <= 0 to automatically calculate tessellation (preferred). Use AddNgon() instead if you need a specific segment count. + IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); // Draw a filled circle - use num_segments <= 0 to automatically calculate tessellation (preferred). Use AddNgonFilled() instead if you need a specific segment count. + IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); // Draw an n-gon with a specific number of sides. Use AddCircle() instead if you want an actual circle and don't care about the exact side count. + IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); // Draw a filled n-gon with a specific number of sides. Use AddCircleFilled() instead if you want an actual circle and don't care about the exact side count. IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ec8c142f..8ce91784 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3502,6 +3502,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::PushItemWidth(100); ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f); if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f; + ImGui::DragFloat("Max circle segment error", &style.CircleSegmentMaxError, 0.01f, 0.1f, 10.0f, "%.2f", 1.0f); ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. ImGui::PopItemWidth(); @@ -4471,7 +4472,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) // First line uses a thickness of 1.0f, second line uses the configurable thickness float th = (n == 0) ? 1.0f : thickness; draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // n-gon - draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 20, th); x += sz + spacing; // Circle + draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 0, th); x += sz + spacing; // Circle draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners @@ -4485,7 +4486,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) y += sz + spacing; } draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // n-gon - draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 32); x += sz + spacing; // Circle + draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 0); x += sz + spacing; // Circle draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 62cf2691..435e689b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -348,6 +348,8 @@ ImDrawListSharedData::ImDrawListSharedData() Font = NULL; FontSize = 0.0f; CurveTessellationTol = 0.0f; + CircleSegmentMaxError = 0.0f; + CircleSegmentCountsMaxCircleSegmentError = -FLT_MIN; // Impossible value to force recalculation ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f); InitialFlags = ImDrawListFlags_None; @@ -1083,11 +1085,34 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV PathFillConvex(col); } +void ImDrawListSharedData::RecalculateCircleSegmentCounts() +{ + for (int i = 0; i < NumCircleSegmentCounts; i++) + { + const float radius = i + 1.0f; + CircleSegmentCounts[i] = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - CircleSegmentMaxError) / radius)), 3, 10000); + } + + CircleSegmentCountsMaxCircleSegmentError = CircleSegmentMaxError; +} + void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) + if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f)) return; + // Calculate number of segments if required + if (num_segments <= 0) + { + int radius_int = (int)radius; + if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts) + num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value + else + num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000); + } + else + num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); @@ -1096,9 +1121,21 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) + if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f)) return; + // Calculate number of segments if required + if (num_segments <= 0) + { + int radius_int = (int)radius; + if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts) + num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value + else + num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000); + } + else + num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); diff --git a/imgui_internal.h b/imgui_internal.h index 5065255c..6679219d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -855,6 +855,7 @@ struct IMGUI_API ImDrawListSharedData ImFont* Font; // Current/default font (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() + float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) @@ -862,6 +863,13 @@ struct IMGUI_API ImDrawListSharedData // FIXME: Bake rounded corners fill/borders in atlas ImVec2 CircleVtx12[12]; + // Cached circle segment counts for the first radii (to avoid calculation overhead) + static const int NumCircleSegmentCounts = 64;// Number of circle segment counts to cache (i.e. the maximum radius before we calculate dynamically) + int CircleSegmentCounts[NumCircleSegmentCounts]; // The segment count for radius (array index + 1) + float CircleSegmentCountsMaxCircleSegmentError; // The MaxCircleSegmentError used to calculate these counts + + void RecalculateCircleSegmentCounts(); // Recalculate circle segment counts based on the current MaxCircleSegmentError + ImDrawListSharedData(); }; From 5363af7f47573c8a9231bc44bc6252188affea08 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 8 Jan 2020 00:10:18 +0100 Subject: [PATCH 14/17] AddCircle, AddCircleFilled: Add auto-calculation of circle segment counts (amends) Tweak default max error value, Changelog, comments, path-fast for 12 segments circles, made LUT store ImU8 --- docs/CHANGELOG.txt | 3 ++ imgui.cpp | 9 ++---- imgui.h | 11 ++++--- imgui_demo.cpp | 31 ++++++++++++------- imgui_draw.cpp | 76 ++++++++++++++++++++++++++++------------------ imgui_internal.h | 20 ++++++------ 6 files changed, 89 insertions(+), 61 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 11afd5e4..f7c903f2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,7 @@ Breaking Changes: documented (can only unreserve from the last reserve call). If you suspect you ever used that feature before, #define IMGUI_DEBUG_PARANOID in imconfig.h to catch existing calls. [@ShironekoBen] +- ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius. - Limiting Columns()/BeginColumns() api to 64 columns with an assert. While the current code technically supports it, future code may not so we're putting the restriction ahead. - imgui_internal.h: changed ImRect() default constructor initializes all fields to 0.0f instead @@ -70,6 +71,8 @@ Other Changes: those improvements in 1.73 makes them unnecessary. (#2722, #2770). [@rokups] - ColorEdit: "Copy As" context-menu tool shows hex values with a '#' prefix instead of '0x'. - ColorEdit: "Copy As" content-menu tool shows hex values both with/without alpha when available. +- ImDrawList: AddCircle(), AddCircleFilled() API can now auto-tessellate when provided a segment + count of zero. Alter tessellation quality with 'style.CircleSegmentMaxError'. [@ShironekoBen] - ImDrawList: Add AddNgon(), AddNgonFilled() API with a guarantee on the explicit segment count. In the current branch they are essentially the same as AddCircle(), AddCircleFilled() but as we will rework the circle rendering functions to use textures and automatic segment count diff --git a/imgui.cpp b/imgui.cpp index 75b95ba5..6ec427e5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -362,6 +362,7 @@ CODE When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more. - 2019/12/17 (1.75) - made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead. - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value. - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017): @@ -988,7 +989,7 @@ ImGuiStyle::ImGuiStyle() AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - CircleSegmentMaxError = 0.75f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. + CircleSegmentMaxError = 1.60f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. // Default theme ImGui::StyleColorsDark(this); @@ -3624,7 +3625,7 @@ void ImGui::NewFrame() IM_ASSERT(g.Font->IsLoaded()); g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; - g.DrawListSharedData.CircleSegmentMaxError = g.Style.CircleSegmentMaxError; + g.DrawListSharedData.SetCircleSegmentMaxError(g.Style.CircleSegmentMaxError); g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; if (g.Style.AntiAliasedLines) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; @@ -3633,10 +3634,6 @@ void ImGui::NewFrame() if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; - // Recalculate circle segment counts if the segment error has changed - if (g.DrawListSharedData.CircleSegmentMaxError != g.DrawListSharedData.CircleSegmentCountsMaxCircleSegmentError) - g.DrawListSharedData.RecalculateCircleSegmentCounts(); - g.BackgroundDrawList.Clear(); g.BackgroundDrawList.PushTextureID(g.IO.Fonts->TexID); g.BackgroundDrawList.PushClipRectFullScreen(); diff --git a/imgui.h b/imgui.h index 7582aafc..5fab99dc 100644 --- a/imgui.h +++ b/imgui.h @@ -1941,6 +1941,9 @@ struct ImDrawList // Primitives // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. + // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). + // In future versions we will use textures to provide cheaper and higher-quality circles. + // Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides. IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4 bits corresponding to which corner to round IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) @@ -1949,10 +1952,10 @@ struct ImDrawList IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col); IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f); IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); - IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); // Draw a circle - use num_segments <= 0 to automatically calculate tessellation (preferred). Use AddNgon() instead if you need a specific segment count. - IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); // Draw a filled circle - use num_segments <= 0 to automatically calculate tessellation (preferred). Use AddNgonFilled() instead if you need a specific segment count. - IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); // Draw an n-gon with a specific number of sides. Use AddCircle() instead if you want an actual circle and don't care about the exact side count. - IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); // Draw a filled n-gon with a specific number of sides. Use AddCircleFilled() instead if you want an actual circle and don't care about the exact side count. + IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); + IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); + IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); + IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8ce91784..05051913 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3500,9 +3500,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well."); ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); ImGui::PushItemWidth(100); - ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f); + ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f"); if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f; - ImGui::DragFloat("Max circle segment error", &style.CircleSegmentMaxError, 0.01f, 0.1f, 10.0f, "%.2f", 1.0f); + ImGui::DragFloat("Circle segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f"); ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. ImGui::PopItemWidth(); @@ -4455,24 +4455,33 @@ static void ShowExampleAppCustomRendering(bool* p_open) static float sz = 36.0f; static float thickness = 3.0f; static int ngon_sides = 6; + static bool circle_segments_override = false; + static int circle_segments_override_v = 12; static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); + ImGui::PushItemWidth(-ImGui::GetFontSize() * 10); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); - ImGui::SliderInt("n-gon sides", &ngon_sides, 3, 12); + ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12); + ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40)) + circle_segments_override = true; ImGui::ColorEdit4("Color", &colf.x); + ImGui::PopItemWidth(); const ImVec2 p = ImGui::GetCursorScreenPos(); const ImU32 col = ImColor(colf); + const float spacing = 10.0f; + const ImDrawCornerFlags corners_none = 0; + const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All; + const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight; + const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; float x = p.x + 4.0f, y = p.y + 4.0f; - float spacing = 10.0f; - ImDrawCornerFlags corners_none = 0; - ImDrawCornerFlags corners_all = ImDrawCornerFlags_All; - ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight; for (int n = 0; n < 2; n++) { // First line uses a thickness of 1.0f, second line uses the configurable thickness float th = (n == 0) ? 1.0f : thickness; - draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // n-gon - draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 0, th); x += sz + spacing; // Circle + draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon + draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners @@ -4485,8 +4494,8 @@ static void ShowExampleAppCustomRendering(bool* p_open) x = p.x + 4; y += sz + spacing; } - draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // n-gon - draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 0); x += sz + spacing; // Circle + draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // N-gon + draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments);x += sz + spacing; // Circle draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 435e689b..2f3370e0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -349,16 +349,29 @@ ImDrawListSharedData::ImDrawListSharedData() FontSize = 0.0f; CurveTessellationTol = 0.0f; CircleSegmentMaxError = 0.0f; - CircleSegmentCountsMaxCircleSegmentError = -FLT_MIN; // Impossible value to force recalculation ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f); InitialFlags = ImDrawListFlags_None; - // Const data + // Lookup tables for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++) { const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12); CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a)); } + memset(CircleSegmentCounts, 0, sizeof(CircleSegmentCounts)); // This will be set by +} + +void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) +{ + if (CircleSegmentMaxError == max_error) + return; + CircleSegmentMaxError = max_error; + for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) + { + const float radius = i + 1.0f; + const int segment_count = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError); + CircleSegmentCounts[i] = (ImU8)ImMin(segment_count, 255); + } } void ImDrawList::Clear() @@ -1085,60 +1098,63 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV PathFillConvex(col); } -void ImDrawListSharedData::RecalculateCircleSegmentCounts() -{ - for (int i = 0; i < NumCircleSegmentCounts; i++) - { - const float radius = i + 1.0f; - CircleSegmentCounts[i] = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - CircleSegmentMaxError) / radius)), 3, 10000); - } - - CircleSegmentCountsMaxCircleSegmentError = CircleSegmentMaxError; -} - void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { - if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f)) + if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; - // Calculate number of segments if required + // Obtain segment count if (num_segments <= 0) { - int radius_int = (int)radius; - if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts) - num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value + // Automatic segment count + const int radius_idx = (int)radius - 1; + if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) + num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value else - num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000); + num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); + } + else + { + // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) + num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); } - else - num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); + if (num_segments == 12) + PathArcToFast(center, radius - 0.5f, 0, 12); + else + PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0 || (radius <= 0.0f)) + if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f) return; - // Calculate number of segments if required + // Obtain segment count if (num_segments <= 0) { - int radius_int = (int)radius; - if (radius_int <= ImDrawListSharedData::NumCircleSegmentCounts) - num_segments = _Data->CircleSegmentCounts[radius_int - 1]; // Use cached value + // Automatic segment count + const int radius_idx = (int)radius - 1; + if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) + num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value else - num_segments = ImClamp((int)((IM_PI * 2.0f) / ImAcos((radius - _Data->CircleSegmentMaxError) / radius)), 3, 10000); + num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); } else - num_segments = ImClamp(num_segments, 3, 10000); // Clamp to avoid drawing insanely tessellated shapes + { + // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) + num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); + } // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); + if (num_segments == 12) + PathArcToFast(center, radius, 0, 12); + else + PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } diff --git a/imgui_internal.h b/imgui_internal.h index 6679219d..e1279c05 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -848,7 +848,13 @@ struct ImGuiColumns } }; +// Helper function to calculate a circle's segment count given its radius and a "maximum error" value. +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 12 +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 +#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp((int)((IM_PI * 2.0f) / ImAcos((_RAD - _MAXERROR) / _RAD)), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) + // Data shared between all ImDrawList instances +// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure. struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas @@ -859,18 +865,12 @@ struct IMGUI_API ImDrawListSharedData ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) - // Const data - // FIXME: Bake rounded corners fill/borders in atlas - ImVec2 CircleVtx12[12]; - - // Cached circle segment counts for the first radii (to avoid calculation overhead) - static const int NumCircleSegmentCounts = 64;// Number of circle segment counts to cache (i.e. the maximum radius before we calculate dynamically) - int CircleSegmentCounts[NumCircleSegmentCounts]; // The segment count for radius (array index + 1) - float CircleSegmentCountsMaxCircleSegmentError; // The MaxCircleSegmentError used to calculate these counts - - void RecalculateCircleSegmentCounts(); // Recalculate circle segment counts based on the current MaxCircleSegmentError + // [Internal] Lookup tables + ImVec2 CircleVtx12[12]; // FIXME: Bake rounded corners fill/borders in atlas + ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius (array index + 1) before we calculate it dynamically (to avoid calculation overhead) ImDrawListSharedData(); + void SetCircleSegmentMaxError(float max_error); }; struct ImDrawDataBuilder From f6da5000bfaf3a035e8d8a7db9b5150644f4630b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 23 Jan 2020 16:20:10 +0100 Subject: [PATCH 15/17] Backends: OpenGL2: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. (#3000) --- docs/CHANGELOG.txt | 2 ++ examples/imgui_impl_opengl2.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f7c903f2..28b792ff 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -171,6 +171,8 @@ Other Changes: - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: Emscripten: Removed BINARYEN_TRAP_MODE=clamp from Makefile which was removed in Emscripten 1.39.0 but required prior to 1.39.0, making life easier for absolutely no-one. (#2877, #2878) [@podsvirov] +- Backends: OpenGL2: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with + legacy OpenGL applications. (#3000) - Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(), using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index de4b128c..b062697b 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-01-23: OpenGL: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -89,6 +90,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function: @@ -126,6 +128,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); // Setup desired GL state @@ -193,6 +196,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); } bool ImGui_ImplOpenGL2_CreateFontsTexture() From b887259974cf1b6587e86f7c9ca7086119303520 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Mon, 27 Jan 2020 14:11:29 +0300 Subject: [PATCH 16/17] Bindings: Improved FreeGLUT support for MinGW (#3004) --- examples/example_glut_opengl2/Makefile | 8 +++++++- examples/example_glut_opengl2/main.cpp | 4 ++-- examples/imgui_impl_glut.cpp | 5 +++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/examples/example_glut_opengl2/Makefile b/examples/example_glut_opengl2/Makefile index c381c0c9..70576b8f 100644 --- a/examples/example_glut_opengl2/Makefile +++ b/examples/example_glut_opengl2/Makefile @@ -41,7 +41,13 @@ endif ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 -lglut + LIBS += -lgdi32 -lopengl32 -limm32 +ifeq ($(shell pkg-config freeglut --exists 2> /dev/null && echo yes || echo no),yes) + CXXFLAGS += $(shell pkg-config freeglut --cflags) + LIBS += $(shell pkg-config freeglut --libs) +else + LIBS += -lglut +endif CFLAGS = $(CXXFLAGS) endif diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index 03db3fce..d36c1f84 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -6,8 +6,8 @@ // !!! Nowadays, prefer using GLFW or SDL instead! #include "imgui.h" -#include "../imgui_impl_glut.h" -#include "../imgui_impl_opengl2.h" +#include "imgui_impl_glut.h" +#include "imgui_impl_opengl2.h" #ifdef __APPLE__ #include #else diff --git a/examples/imgui_impl_glut.cpp b/examples/imgui_impl_glut.cpp index fe519d9c..3c17bbfc 100644 --- a/examples/imgui_impl_glut.cpp +++ b/examples/imgui_impl_glut.cpp @@ -39,7 +39,12 @@ static int g_Time = 0; // Current time, in milliseconds bool ImGui_ImplGLUT_Init() { ImGuiIO& io = ImGui::GetIO(); + +#ifdef FREEGLUT + io.BackendPlatformName ="imgui_impl_glut (freeglut)"; +#else io.BackendPlatformName ="imgui_impl_glut"; +#endif g_Time = 0; From 4d4e3b97f4c9950ccb92986c8f201b2923a8ec61 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 24 Jan 2020 15:25:47 +0100 Subject: [PATCH 17/17] TODO, Readme (dropped TreeNode_NoIndent flag from todo, as it feels unnecessary) --- docs/CHANGELOG.txt | 1 + docs/README.md | 4 ++-- docs/TODO.txt | 33 +++++++++++++++++---------------- examples/README.txt | 16 ++++++---------- imgui_internal.h | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 28b792ff..d05ae4df 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,7 @@ Other Changes: XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput, the later may be problematic if compiling with recent Windows SDK and you want your app to run on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716) +- Backends: Glut: Improved FreeGLUT support for MinGW. (#3004) [@podsvirov] - CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups] - Examples: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might diff --git a/docs/README.md b/docs/README.md index 2bad5cae..37952f06 100644 --- a/docs/README.md +++ b/docs/README.md @@ -113,8 +113,8 @@ Officially maintained bindings (in repository): - Frameworks: Emscripten, Allegro5, Marmalade. Third-party bindings (see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings/) page): -- Languages: C, C#/.Net, ChaiScript, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Irrlicht, Ogre, OpenFrameworks, OSG/OpenSceneGraph, ORX, px_render, LÖVE+Lua, Magnum, NanoRT, Qt, QtDirect3D, SFML, Software Rasterizers, Unreal Engine 4... +- Languages: C, C#/.Net, ChaiScript, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, px_render, Qt/QtDirect3D, SFML, Sokol, Unreal Engine 4, vtk, Win32 GDI. - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. diff --git a/docs/TODO.txt b/docs/TODO.txt index 57680c1e..1184ce50 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -218,21 +218,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer. - menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot). - - text: selectable text (for copy) as a generic feature (ItemFlags?) - - text: proper alignment options in imgui_internal.h - - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? - - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT - - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not - - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use? - - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width - - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings? - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - tree node: tweak color scheme to distinguish headers from selected tree node (#581) - tree node: leaf/non-leaf highlight mismatch. - - tree node: _NoIndentOnOpen flag? would require to store a per-depth bit mask to store info for pop (or whatever is cheaper) - tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height?) - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? @@ -281,6 +271,17 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - pie menus patterns (#434) - markup: simple markup language for color change? (#902) + - text: selectable text (for copy) as a generic feature (ItemFlags?) + - text: proper alignment options in imgui_internal.h + - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #? + - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT + - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not + - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use? + - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width. + - text/wrapped: custom separator for text wrapping. (#3002) + - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) + + - font: arbitrary line spacing. (#2945) - 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). @@ -312,8 +313,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?) ! nav: never clear NavId on some setup (e.g. gamepad centric) - - nav: restore NavId on reappearing non-child window. - - nav: code to focus child-window on restoring NavId appears to have issue (to investigate) + - nav: code to focus child-window on restoring NavId appears to have issue: e.g. when focus change is implicit because of window closure. - 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" @@ -321,20 +321,21 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - 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: 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: 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. - nav: NavFlattened: init request doesn't select items that are part of a NavFlattened child - nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..). - - nav: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) + - nav/treenode: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) - nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons. - nav/menus: allow pressing Menu to leave a sub-menu. - - nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) + - nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar? - nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it? - nav/menus: main menu bar currently cannot restore a NULL focus. Could save NavWindow at the time of being focused, similarly to what popup do? + - nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition? + - nav/windowing: configure fade-in/fade-out delay on Ctrl+Tab? + - nav/windowing: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - nav: simulate right-click or context activation? (SHIFT+F10) - nav: tabs should go through most/all widgets (in submission order?). - - nav: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - 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. diff --git a/examples/README.txt b/examples/README.txt index da05b056..5f45fad9 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -131,22 +131,18 @@ Third-party framework, graphics API and languages bindings are listed at: https://github.com/ocornut/imgui/wiki/Bindings - Languages: - C, C#, ChaiScript, CovScript, D, Go, Haxe/hxcpp, Java, JavaScript, Julia, Lua, Nim, - Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +Including backends for: - Frameworks: - Amethyst, bsf, Cinder, Cocoa2d-x, Diligent Engine, Flexium, GML/GameMaker Studio, - GTK3 + OpenGL, Irrlicht, Ogre, OpenSceneGraph/OSG, openFrameworks, Orx, LÖVE+LUA, - Magnum, NanoRT, Nim Game Lib, px_render, Qt, Qt3d, SFML, Sokol, Unreal Engine 4, vtk... - - Miscellaneous: Software Renderer, RemoteImgui, imgui-ws, etc. + AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, + GML/Game Maker Studio2, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, Nim Game Lib, + Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, px_render, Qt/QtDirect3D, SFML, Sokol, + Unreal Engine 4, vtk, Win32 GDI, etc. Not sure which to use? Recommended platform/frameworks: GLFW https://github.com/glfw/glfw Use imgui_impl_glfw.cpp - SDL2 https://www.libsdl.org Use imgui_impl_sdl.cp + SDL2 https://www.libsdl.org Use imgui_impl_sdl.cpp Sokol https://github.com/floooh/sokol Use util/sokol_imgui.h in Sokol repository. Those will allow you to create portable applications and will solve and abstract away many issues. diff --git a/imgui_internal.h b/imgui_internal.h index e1279c05..f5c5f384 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1664,7 +1664,7 @@ namespace ImGui IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void MarkItemEdited(ImGuiID id); - IMGUI_API void PushOverrideID(ImGuiID id); + IMGUI_API void PushOverrideID(ImGuiID id); // Push given value at the top of the ID stack (whereas PushID combines old and new hashes) // Basic Helpers for widget code IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);