From f0fc8228373ff627de3f453a6a5344e69d0b1dea Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Mar 2021 19:09:08 +0200 Subject: [PATCH 01/16] Fix popup positioning, broken by 84e6fe4. (#3991, #3982) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a7ff0b9d4..5aa1d50cc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5851,6 +5851,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS // Update contents size from last frame for auto-fitting (or use explicit size) + const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0); CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal); if (window->HiddenFramesCanSkipItems > 0) window->HiddenFramesCanSkipItems--; @@ -5981,7 +5982,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Pos = parent_window->DC.CursorPos; } - const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0); const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0); if (window_pos_with_pivot) SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering) From 00d570e280533bca9cf6e5652d0f2eb131d032e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 1 Apr 2021 17:18:18 +0200 Subject: [PATCH 02/16] Added OpenPopup() ImGuiID overload (#3993, #331) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++++ imgui.h | 1 + 3 files changed, 7 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8dcbbae52..c12664716 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,7 @@ Other Changes: consistent with the compile-time default. (#3922) - DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler] - ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack] +- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] - Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961) diff --git a/imgui.cpp b/imgui.cpp index 5aa1d50cc..67193e1b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8093,6 +8093,11 @@ void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) OpenPopupEx(g.CurrentWindow->GetID(str_id), popup_flags); } +void ImGui::OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags) +{ + OpenPopupEx(id, popup_flags); +} + // Mark popup as open (toggle toward open state). // Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. // Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). diff --git a/imgui.h b/imgui.h index 5aa31bb75..cb6c753b4 100644 --- a/imgui.h +++ b/imgui.h @@ -653,6 +653,7 @@ namespace ImGui // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup(). // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened. IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). + IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. // Popups: open+begin combined functions helpers From feb8b1e32df4af887ed1e98115372398c7bc43f5 Mon Sep 17 00:00:00 2001 From: TotalCaesar659 <14265316+TotalCaesar659@users.noreply.github.com> Date: Tue, 6 Apr 2021 10:16:35 +0300 Subject: [PATCH 03/16] Update URLs to HTTPS (#4011) --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index b055ac659..77015ef27 100644 --- a/docs/README.md +++ b/docs/README.md @@ -199,7 +199,7 @@ Ongoing Dear ImGui development is currently financially supported by users and p - [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui/) *Double-chocolate and Salty caramel sponsors* -- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [Supercell](http://www.supercell.com) +- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [Supercell](https://supercell.com) Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors. From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations. @@ -214,12 +214,12 @@ Dear ImGui is using software and services provided free of charge for open sourc Credits ------- -Developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com) (PS Vita). +Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita). Recurring contributors (2020): Omar Cornut [@ocornut](https://github.com/ocornut), Rokas Kupstys [@rokups](https://github.com/rokups), Ben Carter [@ShironekoBen](https://github.com/ShironekoBen). A large portion of work on automation systems, regression tests and other features are currently unpublished. -Omar: "I first discovered the IMGUI paradigm at [Q-Games](http://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it." +Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it." Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license). From f08566b4d7b0fa1afe02856af24bcac60f792486 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Tue, 6 Apr 2021 12:00:38 +0200 Subject: [PATCH 04/16] InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 1 + imgui_widgets.cpp | 30 +++++++++++++++++------------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c12664716..48b756b8c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,7 @@ Other Changes: consistent with the compile-time default. (#3922) - DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler] - ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack] +- InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks] - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] diff --git a/imgui_internal.h b/imgui_internal.h index 051270ffa..041e8e5ee 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -827,6 +827,7 @@ enum ImGuiInputSource ImGuiInputSource_Keyboard, ImGuiInputSource_Gamepad, ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only + ImGuiInputSource_Clipboard, // Currently only used by InputText() ImGuiInputSource_COUNT }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4098c0667..6274b06d8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -122,7 +122,7 @@ static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); //------------------------------------------------------------------------- // For InputTextEx() -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data); +static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source); static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); @@ -3764,8 +3764,9 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons } // Return false to discard a character. -static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source) { + IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard); unsigned int c = *p_char; // Filter non-printable (NB: isprint is unreliable! see #2467) @@ -3778,15 +3779,18 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f return false; } - // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) - if (c == 127) - return false; + if (input_source != ImGuiInputSource_Clipboard) + { + // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) + if (c == 127) + return false; - // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) - if (c >= 0xE000 && c <= 0xF8FF) - return false; + // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) + if (c >= 0xE000 && c <= 0xF8FF) + return false; + } - // Filter Unicode ranges we are not handling in this build. + // Filter Unicode ranges we are not handling in this build if (c > IM_UNICODE_CODEPOINT_MAX) return false; @@ -4111,7 +4115,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (!io.InputQueueCharacters.contains('\t')) { unsigned int c = '\t'; // Insert TAB - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) + if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } @@ -4126,7 +4130,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ unsigned int c = (unsigned int)io.InputQueueCharacters[n]; if (c == '\t' && io.KeyShift) continue; - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) + if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } @@ -4190,7 +4194,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else if (!is_readonly) { unsigned int c = '\n'; // Insert new line - if (InputTextFilterCharacter(&c, flags, callback, callback_user_data)) + if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } } @@ -4243,7 +4247,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ s += ImTextCharFromUtf8(&c, s, NULL); if (c == 0) break; - if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data)) + if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard)) continue; clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; } From 71dda216efd3ad444a1fceb8baea489e16e15b3d Mon Sep 17 00:00:00 2001 From: Sam Jones Date: Tue, 6 Apr 2021 12:36:52 +0200 Subject: [PATCH 05/16] Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) --- backends/imgui_impl_opengl3.cpp | 14 +++++++++----- docs/CHANGELOG.txt | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index b582851e8..8519c64a6 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. // 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer. // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. // 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. @@ -262,11 +263,14 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid #endif // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) +#if defined(GL_CLIP_ORIGIN) bool clip_origin_lower_left = true; - GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); - if (current_clip_origin == GL_UPPER_LEFT) - clip_origin_lower_left = false; + if (g_GlVersion >= 450) + { + GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); + if (current_clip_origin == GL_UPPER_LEFT) + clip_origin_lower_left = false; + } #endif // Setup viewport, orthographic projection matrix @@ -276,7 +280,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) +#if defined(GL_CLIP_ORIGIN) if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left #endif const float ortho_projection[4][4] = diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 48b756b8c..de5424272 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,7 @@ Other Changes: workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857) - Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994] +- Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones] - Examples: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx] - Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881) - Examples: SDL2: Link with shell32.lib required by SDL2main.lib since SDL 2.0.12. [#3988] From 5f45047fb67c2147c6a1b1798b98d401e7998b51 Mon Sep 17 00:00:00 2001 From: Peter Kristensen Date: Sat, 3 Apr 2021 16:03:37 +0200 Subject: [PATCH 06/16] Update example makefiles to check the new homebrew paths (#4003) Homebrew on Apple Silicon (i.e. Macbook Air/Pro M1) use `/opt/homebrew` instead of /usr/local. --- examples/example_glfw_metal/Makefile | 5 +++-- examples/example_glfw_opengl2/Makefile | 4 ++-- examples/example_glfw_opengl3/Makefile | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/example_glfw_metal/Makefile b/examples/example_glfw_metal/Makefile index 8f08b9657..a174bc8f2 100644 --- a/examples/example_glfw_metal/Makefile +++ b/examples/example_glfw_metal/Makefile @@ -14,9 +14,10 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore -LIBS += -L/usr/local/lib -lglfw +LIBS += -L/usr/local/lib -L/opt/homebrew/lib +LIBS += -lglfw -CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include +CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include CXXFLAGS += -Wall -Wformat CFLAGS = $(CXXFLAGS) diff --git a/examples/example_glfw_opengl2/Makefile b/examples/example_glfw_opengl2/Makefile index 720a403c3..5c19a27f1 100644 --- a/examples/example_glfw_opengl2/Makefile +++ b/examples/example_glfw_opengl2/Makefile @@ -41,11 +41,11 @@ endif ifeq ($(UNAME_S), Darwin) #APPLE ECHO_MESSAGE = "Mac OS X" LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo - LIBS += -L/usr/local/lib -L/opt/local/lib + LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib #LIBS += -lglfw3 LIBS += -lglfw - CXXFLAGS += -I/usr/local/include -I/opt/local/include + CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include CFLAGS = $(CXXFLAGS) endif diff --git a/examples/example_glfw_opengl3/Makefile b/examples/example_glfw_opengl3/Makefile index cfa31cd68..15eb72a22 100644 --- a/examples/example_glfw_opengl3/Makefile +++ b/examples/example_glfw_opengl3/Makefile @@ -80,11 +80,11 @@ endif ifeq ($(UNAME_S), Darwin) #APPLE ECHO_MESSAGE = "Mac OS X" LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo - LIBS += -L/usr/local/lib -L/opt/local/lib + LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib #LIBS += -lglfw3 LIBS += -lglfw - CXXFLAGS += -I/usr/local/include -I/opt/local/include + CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include CFLAGS = $(CXXFLAGS) endif From 92b7b1f72bc830cede5da5efe064c4f9e1a21838 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 6 Apr 2021 17:51:21 +0200 Subject: [PATCH 07/16] Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index de5424272..d69fb9ebb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,7 @@ Other Changes: - Scrolling: Fix scroll tracking with e.g. SetScrollHereX/Y() when WindowPadding < ItemSpacing. - Scrolling: Fix scroll snapping on edge of scroll region when both scrollbars are enabled. +- Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010) - Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061) - Tables: Expose TableSetColumnEnabled() in public api. (#3935) - TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single diff --git a/imgui.cpp b/imgui.cpp index 67193e1b3..dce61e80f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3738,10 +3738,17 @@ void ImGui::UpdateMouseWheel() // Mouse wheel scrolling // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent + if (g.IO.KeyCtrl) + return; + + // As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead + // (we avoid doing it on OSX as it the OS input layer handles this already) + const bool swap_axis = g.IO.KeyShift && !g.IO.ConfigMacOSXBehaviors; + const float wheel_y = swap_axis ? 0.0f : g.IO.MouseWheel; + const float wheel_x = swap_axis ? g.IO.MouseWheel : g.IO.MouseWheelH; // Vertical Mouse Wheel scrolling - const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; - if (wheel_y != 0.0f && !g.IO.KeyCtrl) + if (wheel_y != 0.0f) { StartLockWheelingWindow(window); while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) @@ -3755,8 +3762,7 @@ void ImGui::UpdateMouseWheel() } // Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held - const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; - if (wheel_x != 0.0f && !g.IO.KeyCtrl) + if (wheel_x != 0.0f) { StartLockWheelingWindow(window); while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)))) From c283a1da5bab8f8492e0c5b4ac9f3bd71adc05c2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 6 Apr 2021 18:35:06 +0200 Subject: [PATCH 08/16] Fixed clipping of multi-line value text when label is single-line + Fixed vertical alignment of single-line value text when label is multi-line. (#4004) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 13 ++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d69fb9ebb..06999251e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,8 @@ Other Changes: - DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler] - ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack] - InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks] +- LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004) +- LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004) - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6274b06d8..d4d39143f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -350,17 +350,20 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) const ImGuiStyle& style = g.Style; const float w = CalcItemWidth(); + const char* value_text_begin = &g.TempBuffer[0]; + const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false); const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2)); - const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y * 2) + label_size); + + const ImVec2 pos = window->DC.CursorPos; + const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2)); + const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, 0)) return; // Render - const char* value_text_begin = &g.TempBuffer[0]; - const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); - RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f, 0.5f)); + RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); } From bcdc8bcc4b8a30a1e0451b96ba51d68e4cab9b09 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 6 Apr 2021 11:11:59 +0300 Subject: [PATCH 09/16] Examples: Vulkan: Update GPU selection to pick discrete GPU if available, or use first GPU otherwise. (#4012) Fixes examples failing on optimus laptops with integrated graphics not supporting Vulkan. --- docs/CHANGELOG.txt | 1 + examples/example_glfw_vulkan/main.cpp | 20 ++++++++++++++++---- examples/example_sdl_vulkan/main.cpp | 20 ++++++++++++++++---- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 06999251e..954b3fd8a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,6 +65,7 @@ Other Changes: - Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones] - Examples: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx] - Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881) +- Examples: Vulkan: Prefer using discrete GPU if there are more than one available. (#4012) [@rokups] - Examples: SDL2: Link with shell32.lib required by SDL2main.lib since SDL 2.0.12. [#3988] - Docs: Improvements to minor mistakes in documentation comments (#3923) [@ANF-Studios] diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 3b1a0d516..615f2ee1d 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -122,10 +122,22 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus); check_vk_result(err); - // If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose - // e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc. - // for sake of simplicity we'll just take the first one, assuming it has a graphics queue family. - g_PhysicalDevice = gpus[0]; + // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers + // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple + // dedicated GPUs) is out of scope of this sample. + int use_gpu = 0; + for (int i = 0; i < (int)gpu_count; i++) + { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(gpus[i], &properties); + if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + { + use_gpu = i; + break; + } + } + + g_PhysicalDevice = gpus[use_gpu]; free(gpus); } diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 5ab8d26b1..db577e5e8 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -114,10 +114,22 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus); check_vk_result(err); - // If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose - // e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc. - // for sake of simplicity we'll just take the first one, assuming it has a graphics queue family. - g_PhysicalDevice = gpus[0]; + // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers + // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple + // dedicated GPUs) is out of scope of this sample. + int use_gpu = 0; + for (int i = 0; i < (int)gpu_count; i++) + { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(gpus[i], &properties); + if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + { + use_gpu = i; + break; + } + } + + g_PhysicalDevice = gpus[use_gpu]; free(gpus); } From d6a5cc7934b4f4f9d5effffc4f1acee151247f51 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Apr 2021 17:57:14 +0200 Subject: [PATCH 10/16] Metrics: hotfix (fix 6ba13349 + f08566b4, #4005) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index dce61e80f..035e748c5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11116,7 +11116,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Misc Details if (TreeNode("Internal state")) { - const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); + const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); Text("WINDOWING"); Indent(); From b957300260c389020223548098e886b3cd92e693 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Apr 2021 15:44:56 +0200 Subject: [PATCH 11/16] Documentation tweaks (#4042) --- docs/BACKENDS.md | 2 ++ docs/EXAMPLES.md | 6 +++++- examples/README.txt | 8 +++++++- imgui.cpp | 16 ++++++++-------- imgui.h | 4 ++-- imgui_draw.cpp | 2 ++ 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index a45fdaa40..2ad719a9b 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -17,6 +17,8 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources. For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details. +**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.** + ### What are backends diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 34261edbb..979539bf8 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -3,7 +3,11 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/EXAMP ## Dear ImGui: Examples **The [examples/](https://github.com/ocornut/imgui/blob/master/examples) folder example applications (standalone, ready-to-build) for variety of -platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder. +platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder (see [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md)). + +The purpose of Examples is to showcase integration with backends, let you try Dear ImGui, and guide you toward +integrating Dear ImGui in your own application/game/engine. +**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.** You can find Windows binaries for some of those example applications at: http://www.dearimgui.org/binaries diff --git a/examples/README.txt b/examples/README.txt index ed16dd9f2..2c71387ea 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1 +1,7 @@ -See EXAMPLES and BACKENDS files in the docs/ folder. +See BACKENDS and EXAMPLES files in the docs/ folder. + +Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app). +Examples = Standalone applications showcasing integration with platforms/graphics api. + +Once Dear ImGui is running (in either examples or your own application/game/engine), +run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API. diff --git a/imgui.cpp b/imgui.cpp index 035e748c5..7a1460fb8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11,16 +11,16 @@ // - FAQ http://dearimgui.org/faq // - Homepage & latest https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!) +// - Gallery https://github.com/ocornut/imgui/issues/3793 (please post your screenshots/video there!) +// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Wiki https://github.com/ocornut/imgui/wiki // - Issues & support https://github.com/ocornut/imgui/issues // - Discussions https://github.com/ocornut/imgui/discussions // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but needs your support to sustain development and maintenance. -// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.org". +// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.com". // Individuals: you can support continued development via donations. See docs/README or web page. // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. @@ -134,13 +134,13 @@ CODE READ FIRST ---------- - - Remember to read the FAQ (https://www.dearimgui.org/faq) + - Remember to check the wonderful Wiki (https://github.com/ocornut/imgui/wiki) - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, fewer bugs. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build. - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori). - You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in the FAQ. + You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki. - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances. For every application frame, your UI code will be called only once. This is in contrast to e.g. Unity's implementation of an IMGUI, where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches. @@ -576,7 +576,7 @@ CODE - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset. - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity. - - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). + - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetID() and use it instead of passing string to BeginChild(). - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully, breakage should be minimal. @@ -744,14 +744,14 @@ CODE ============== Q: How can I help? - A: - Businesses: please reach out to "contact AT dearimgui.org" if you work in a place using Dear ImGui! + A: - Businesses: please reach out to "contact AT dearimgui.com" if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people working on this project. - Individuals: you can support continued development via PayPal donations. See README. - If you are experienced with Dear ImGui and C++, look at the GitHub issues, look at the Wiki, read docs/TODO.txt and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. + You may post screenshot or links in the gallery threads. Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui helps the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on GitHub or privately). diff --git a/imgui.h b/imgui.h index cb6c753b4..9e1bb56f5 100644 --- a/imgui.h +++ b/imgui.h @@ -11,9 +11,9 @@ // - FAQ http://dearimgui.org/faq // - Homepage & latest https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases -// - Gallery https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!) +// - Gallery https://github.com/ocornut/imgui/issues/3793 (please post your screenshots/video there!) +// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary -// - Wiki https://github.com/ocornut/imgui/wiki // - Issues & support https://github.com/ocornut/imgui/issues // - Discussions https://github.com/ocornut/imgui/discussions diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 647addc67..e08e9d7dc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3469,6 +3469,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons return text_size; } +// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const { const ImFontGlyph* glyph = FindGlyph(c); @@ -3483,6 +3484,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } +// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const { if (!text_end) From 05a20ca738d8610d977bdfac5f4a75a29457aaf1 Mon Sep 17 00:00:00 2001 From: duddel Date: Wed, 14 Apr 2021 21:43:53 +0200 Subject: [PATCH 12/16] Examples: Android: Make Android build compatible with Gradle 7.0. (#3446) --- docs/CHANGELOG.txt | 3 ++- examples/example_android_opengl3/android/build.gradle | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 954b3fd8a..564c8a353 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,10 +63,11 @@ Other Changes: - Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994] - Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones] -- Examples: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx] +- Examples: OpenGL: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx] - Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881) - Examples: Vulkan: Prefer using discrete GPU if there are more than one available. (#4012) [@rokups] - Examples: SDL2: Link with shell32.lib required by SDL2main.lib since SDL 2.0.12. [#3988] +- Examples: Android: Make Android example build compatible with Gradle 7.0. (#3446) - Docs: Improvements to minor mistakes in documentation comments (#3923) [@ANF-Studios] diff --git a/examples/example_android_opengl3/android/build.gradle b/examples/example_android_opengl3/android/build.gradle index 44603ea38..59f9c78e4 100644 --- a/examples/example_android_opengl3/android/build.gradle +++ b/examples/example_android_opengl3/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.4.30' + ext.kotlin_version = '1.4.31' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } @@ -15,7 +15,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } From 858ea17eba47e17c7a2e4acb5a5678320d7b1290 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Apr 2021 13:29:42 +0200 Subject: [PATCH 13/16] Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when entering the rendering function. (#4045) --- backends/imgui_impl_dx10.cpp | 2 +- backends/imgui_impl_dx11.cpp | 2 +- docs/CHANGELOG.txt | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 288427553..33be9389a 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -190,7 +190,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) DXGI_FORMAT IndexBufferFormat; ID3D10InputLayout* InputLayout; }; - BACKUP_DX10_STATE old; + BACKUP_DX10_STATE old = {}; old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index f114cdc15..0690b97bf 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -198,7 +198,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; }; - BACKUP_DX11_STATE old; + BACKUP_DX11_STATE old = {}; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 564c8a353..bcfa40f98 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,8 @@ Other Changes: [@1025798851] - Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857) +- Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when + entering the rendering function. (#4045) [@Nemirtingas] - Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994] - Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones] From 7c9c5dbe9a9804f5186128e363da3197e3ee330e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Apr 2021 14:27:45 +0200 Subject: [PATCH 14/16] Internals: Added ImFloorSigned() + use our own ImFloorSigned() for stb_truetype, compared as matching output for variety of font data. (#2884) --- imgui_draw.cpp | 2 +- imgui_internal.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e08e9d7dc..6c0d10ade 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -145,7 +145,7 @@ namespace IMGUI_STB_NAMESPACE #define STBTT_sqrt(x) ImSqrt(x) #define STBTT_pow(x,y) ImPow(x,y) #define STBTT_fabs(x) ImFabs(x) -#define STBTT_ifloor(x) ((int)ImFloorStd(x)) +#define STBTT_ifloor(x) ((int)ImFloorSigned(x)) #define STBTT_iceil(x) ((int)ImCeil(x)) #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION diff --git a/imgui_internal.h b/imgui_internal.h index 041e8e5ee..cb8924ac9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -64,6 +64,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' +#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok, for ImFloorSigned() #pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h #pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h #pragma clang diagnostic ignored "-Wold-style-cast" @@ -364,7 +365,7 @@ IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* #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 ImFloorStd(X) floorf(X) // We use our own, see ImFloor() and ImFloorSigned() #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); } @@ -396,6 +397,7 @@ static inline float ImLengthSqr(const ImVec2& lhs) static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; } static inline float ImFloor(float f) { return (float)(int)(f); } +static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } From 5fed6bdc72c73f4bf3ac8892778846ff1fdce421 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Apr 2021 15:53:50 +0200 Subject: [PATCH 15/16] Demo: Improved popups demo and comments. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 19 ++++++-- imgui.h | 2 +- imgui_demo.cpp | 106 ++++++++++++++++++++++++++++++--------------- 4 files changed, 89 insertions(+), 39 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bcfa40f98..104cccaff 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004) - LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004) - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] +- Demo: Improved popups demo and comments. - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] - Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961) diff --git a/imgui.cpp b/imgui.cpp index 7a1460fb8..6ce2b950d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8363,10 +8363,21 @@ void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags } // This is a helper to handle the simplest case of associating one named popup to one given widget. -// - You can pass a NULL str_id to use the identifier of the last item. -// - You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). -// - This is essentially the same as calling OpenPopupOnItemClick() + BeginPopup() but written to avoid -// computing the ID twice because BeginPopupContextXXX functions may be called very frequently. +// - To create a popup associated to the last item, you generally want to pass a NULL value to str_id. +// - To create a popup with a specific identifier, pass it in str_id. +// - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call. +// - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id. +// - You may want to handle the whole on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). +// This is essentially the same as: +// id = str_id ? GetID(str_id) : GetItemID(); +// OpenPopupOnItemClick(str_id); +// return BeginPopup(id); +// Which is essentially the same as: +// id = str_id ? GetID(str_id) : GetItemID(); +// if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) +// OpenPopup(id); +// return BeginPopup(id); +// The main difference being that this is tweaked to avoid computing the ID twice. bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiWindow* window = GImGui->CurrentWindow; diff --git a/imgui.h b/imgui.h index 9e1bb56f5..1caf93230 100644 --- a/imgui.h +++ b/imgui.h @@ -661,7 +661,7 @@ namespace ImGui // - They are convenient to easily create context menus, hence the name. // - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future. // - IMPORTANT: we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight. - IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! + IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows). // Popups: query functions diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5ccee4f7f..6cf6848eb 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3192,46 +3192,84 @@ static void ShowDemoWindowPopups() if (ImGui::TreeNode("Context menus")) { + HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier."); + // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing: - // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) - // OpenPopup(id); - // return BeginPopup(id); - // For more advanced uses you may want to replicate and customize this code. - // See details in BeginPopupContextItem(). - static float value = 0.5f; - ImGui::Text("Value = %.3f (<-- right-click here)", value); - if (ImGui::BeginPopupContextItem("item context menu")) + // if (id == 0) + // id = GetItemID(); // Use last item id + // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) + // OpenPopup(id); + // return BeginPopup(id); + // For advanced advanced uses you may want to replicate and customize this code. + // See more details in BeginPopupContextItem(). + + // Example 1 + // When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(), + // and BeginPopupContextItem() will use the last item ID as the popup ID. { - if (ImGui::Selectable("Set to zero")) value = 0.0f; - if (ImGui::Selectable("Set to PI")) value = 3.1415f; - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); - ImGui::EndPopup(); + const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" }; + for (int n = 0; n < 5; n++) + { + ImGui::Selectable(names[n]); + if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id + { + ImGui::Text("This a popup for \"%s\"!", names[n]); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Right-click to open popup"); + } } - // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the - // Begin() call. So here we will make it that clicking on the text field with the right mouse button (1) - // will toggle the visibility of the popup above. - ImGui::Text("(You can also right-click me to open the same popup as above.)"); - ImGui::OpenPopupOnItemClick("item context menu", 1); - - // When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem(). - // BeginPopupContextItem() will use the last item ID as the popup ID. - // In addition here, we want to include your editable label inside the button label. - // We use the ### operator to override the ID (read FAQ about ID for details) - static char name[32] = "Label1"; - char buf[64]; - sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label - ImGui::Button(buf); - if (ImGui::BeginPopupContextItem()) + // Example 2 + // Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem(). + // Using an explicit identifier is also convenient if you want to activate the popups from different locations. { - ImGui::Text("Edit name:"); - ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); - if (ImGui::Button("Close")) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); + HelpMarker("Text() elements don't have stable identifiers so we need to provide one."); + static float value = 0.5f; + ImGui::Text("Value = %.3f <-- (1) right-click this value", value); + if (ImGui::BeginPopupContextItem("my popup")) + { + if (ImGui::Selectable("Set to zero")) value = 0.0f; + if (ImGui::Selectable("Set to PI")) value = 3.1415f; + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); + ImGui::EndPopup(); + } + + // We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup. + // Here we make it that right-clicking this other text element opens the same popup as above. + // The popup itself will be submitted by the code above. + ImGui::Text("(2) Or right-click this text"); + ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight); + + // Back to square one: manually open the same popup. + if (ImGui::Button("(3) Or click this button")) + ImGui::OpenPopup("my popup"); + } + + // Example 3 + // When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID), + // we need to make sure your item identifier is stable. + // In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ). + { + HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator."); + static char name[32] = "Label1"; + char buf[64]; + sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label + ImGui::Button(buf); + if (ImGui::BeginPopupContextItem()) + { + ImGui::Text("Edit name:"); + ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); } - ImGui::SameLine(); ImGui::Text("(<-- right-click here)"); ImGui::TreePop(); } From 690a90bd35fe81d84c01c3a0f1bcd6af812d85e6 Mon Sep 17 00:00:00 2001 From: thedmd Date: Wed, 14 Apr 2021 20:07:23 +0200 Subject: [PATCH 16/16] Make PathArcTo accept counter-clockwise angles (#4030, #3491) --- docs/CHANGELOG.txt | 1 + imgui_draw.cpp | 75 +++++++++++++++++++++++++++------------------- imgui_internal.h | 1 + 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 104cccaff..a1a4d7ef6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004) - LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004) - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] +- ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd] - Demo: Improved popups demo and comments. - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6c0d10ade..2b0fdb8f2 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1037,7 +1037,6 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_ _Path.push_back(center); return; } - IM_ASSERT(a_min_sample <= a_max_sample); // Calculate arc auto segment step size if (a_step <= 0) @@ -1046,17 +1045,7 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_ // Make sure we never do steps larger than one quarter of the circle a_step = ImClamp(a_step, 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4); - // Normalize a_min_sample to always start lie in [0..IM_DRAWLIST_ARCFAST_SAMPLE_MAX] range. - if (a_min_sample < 0) - { - int normalized_sample = a_min_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX; - if (normalized_sample < 0) - normalized_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; - a_max_sample += (normalized_sample - a_min_sample); - a_min_sample = normalized_sample; - } - - const int sample_range = a_max_sample - a_min_sample; + const int sample_range = ImAbs(a_max_sample - a_min_sample); const int a_next_step = a_step; int samples = sample_range + 1; @@ -1082,16 +1071,40 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_ ImVec2* out_ptr = _Path.Data + (_Path.Size - samples); int sample_index = a_min_sample; - for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step) + if (sample_index < 0 || sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX) { - // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more - if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX) - sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX; + sample_index = sample_index % IM_DRAWLIST_ARCFAST_SAMPLE_MAX; + if (sample_index < 0) + sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; + } - const ImVec2 s = _Data->ArcFastVtx[sample_index]; - out_ptr->x = center.x + s.x * radius; - out_ptr->y = center.y + s.y * radius; - out_ptr++; + if (a_max_sample >= a_min_sample) + { + for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step) + { + // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more + if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX) + sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX; + + const ImVec2 s = _Data->ArcFastVtx[sample_index]; + out_ptr->x = center.x + s.x * radius; + out_ptr->y = center.y + s.y * radius; + out_ptr++; + } + } + else + { + for (int a = a_min_sample; a >= a_max_sample; a -= a_step, sample_index -= a_step, a_step = a_next_step) + { + // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more + if (sample_index < 0) + sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; + + const ImVec2 s = _Data->ArcFastVtx[sample_index]; + out_ptr->x = center.x + s.x * radius; + out_ptr->y = center.y + s.y * radius; + out_ptr++; + } } if (extra_max_sample) @@ -1116,7 +1129,6 @@ void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, fl _Path.push_back(center); return; } - IM_ASSERT(a_min <= a_max); // Note that we are adding a point at both a_min and a_max. // If you are trying to draw a full closed circle you don't want the overlapping points! @@ -1136,7 +1148,6 @@ void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_ _Path.push_back(center); return; } - IM_ASSERT(a_min_of_12 <= a_max_of_12); _PathArcToFastEx(center, radius, a_min_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, a_max_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, 0); } @@ -1147,7 +1158,6 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa _Path.push_back(center); return; } - IM_ASSERT(a_min <= a_max); if (num_segments > 0) { @@ -1158,28 +1168,33 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa // Automatic segment count if (radius <= _Data->ArcFastRadiusCutoff) { + const bool a_is_reverse = a_max < a_min; + // We are going to use precomputed values for mid samples. // Determine first and last sample in lookup table that belong to the arc. - const int a_min_sample = (int)ImCeil(IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f)); - const int a_max_sample = (int)( IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f)); - const int a_mid_samples = ImMax(a_max_sample - a_min_sample, 0); + const float a_min_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f); + const float a_max_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f); + + const int a_min_sample = a_is_reverse ? (int)ImFloorSigned(a_min_sample_f) : (int)ImCeil(a_min_sample_f); + const int a_max_sample = a_is_reverse ? (int)ImCeil(a_max_sample_f) : (int)ImFloorSigned(a_max_sample_f); + const int a_mid_samples = a_is_reverse ? ImMax(a_min_sample - a_max_sample, 0) : ImMax(a_max_sample - a_min_sample, 0); const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; - const bool a_emit_start = (a_min_segment_angle - a_min) > 0.0f; - const bool a_emit_end = (a_max - a_max_segment_angle) > 0.0f; + const bool a_emit_start = (a_min_segment_angle - a_min) != 0.0f; + const bool a_emit_end = (a_max - a_max_segment_angle) != 0.0f; _Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0))); if (a_emit_start) _Path.push_back(ImVec2(center.x + ImCos(a_min) * radius, center.y + ImSin(a_min) * radius)); - if (a_max_sample >= a_min_sample) + if (a_mid_samples > 0) _PathArcToFastEx(center, radius, a_min_sample, a_max_sample, 0); if (a_emit_end) _Path.push_back(ImVec2(center.x + ImCos(a_max) * radius, center.y + ImSin(a_max) * radius)); } else { - const float arc_length = a_max - a_min; + const float arc_length = ImAbs(a_max - a_min); const int circle_segment_count = _CalcCircleAutoSegmentCount(radius); const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length)); _PathArcToN(center, radius, a_min, a_max, arc_segment_count); diff --git a/imgui_internal.h b/imgui_internal.h index cb8924ac9..c100cfc9f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -371,6 +371,7 @@ 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 ImLog(float x) { return logf(x); } // DragBehaviorT/SliderBehaviorT uses ImLog with either float/double and need the precision static inline double ImLog(double x) { return log(x); } +static inline int ImAbs(int x) { return x < 0 ? -x : x; } static inline float ImAbs(float x) { return fabsf(x); } static inline double ImAbs(double x) { return fabs(x); } static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument