From 54fb051e52bbff345340972520a2efd5693f066b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 28 Feb 2022 16:12:43 +0100 Subject: [PATCH 01/17] ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 21e783b4..53ec7689 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: - IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the return value is overriden by focus when gamepad/keyboard navigation is active. - Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate. +- ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Stack Tool: Added option to copy item path to clipboard. (#4631) - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 21415a74..64e7aa9c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4997,8 +4997,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) { - const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x; - window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y); + SameLine(0.0f, style.ItemInnerSpacing.x); TextEx(label, label_display_end); } From 1e18da5c380eec9d1b278a9683cacdd59897f0e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 28 Feb 2022 20:50:58 +0100 Subject: [PATCH 02/17] Backends, Examples: Add comments about using WndProc handler and WantCaptureXXX flags. (#5061) + update README. --- backends/imgui_impl_allegro5.cpp | 4 ++-- backends/imgui_impl_sdl.cpp | 4 ++-- backends/imgui_impl_win32.cpp | 6 +++--- backends/imgui_impl_win32.h | 2 ++ docs/README.md | 8 ++++---- examples/example_allegro5/main.cpp | 4 ++-- examples/example_emscripten_opengl3/main.cpp | 4 ++-- examples/example_glfw_metal/main.mm | 4 ++-- examples/example_glfw_opengl2/main.cpp | 4 ++-- examples/example_glfw_opengl3/main.cpp | 4 ++-- examples/example_glfw_vulkan/main.cpp | 4 ++-- examples/example_glut_opengl2/main.cpp | 5 +++-- examples/example_sdl_directx11/main.cpp | 4 ++-- examples/example_sdl_metal/main.mm | 4 ++-- examples/example_sdl_opengl2/main.cpp | 4 ++-- examples/example_sdl_opengl3/main.cpp | 4 ++-- examples/example_sdl_sdlrenderer/main.cpp | 4 ++-- examples/example_sdl_vulkan/main.cpp | 4 ++-- examples/example_win32_directx10/main.cpp | 9 +++++---- examples/example_win32_directx11/main.cpp | 9 +++++---- examples/example_win32_directx12/main.cpp | 9 +++++---- examples/example_win32_directx9/main.cpp | 9 +++++---- 22 files changed, 60 insertions(+), 53 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index dcc806a6..542fe129 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -456,8 +456,8 @@ static void ImGui_ImplAllegro5_UpdateKeyModifiers() } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) { diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 9764cb2d..ef5ef609 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -237,8 +237,8 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field. bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 157b57de..ee951fc7 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -488,10 +488,10 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) #endif // Win32 message handler (process Win32 mouse/keyboard inputs, etc.) -// Call from your application's message handler. +// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. // When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds. // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. diff --git a/backends/imgui_impl_win32.h b/backends/imgui_impl_win32.h index a04b6a71..082461dd 100644 --- a/backends/imgui_impl_win32.h +++ b/backends/imgui_impl_win32.h @@ -22,6 +22,8 @@ IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); // Win32 message handler your application need to call. // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. +// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. + #if 0 extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); #endif diff --git a/docs/README.md b/docs/README.md index 6569f454..54ca5c78 100644 --- a/docs/README.md +++ b/docs/README.md @@ -195,7 +195,7 @@ See [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page. Sponsors -------- -Ongoing Dear ImGui development is currently financially supported by users and private sponsors: +Ongoing Dear ImGui development is currently financially supported in 2021-2022 by users and private sponsors: *Platinum-chocolate sponsors* - [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1) @@ -204,12 +204,12 @@ Ongoing Dear ImGui development is currently financially supported by users and p - [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui), [Supercell](https://supercell.com) *Chocolate sponsors* -- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [RAD Game Tools](http://www.radgametools.com/) +- [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Epic](https://www.unrealengine.com/en-US/megagrants), [G3Dvu](). *Salty-caramel sponsors* -- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com) +- [Kylotonn](https://www.kylotonn.com), [O-Net Communications (USA)](http://en.o-netcom.com), [Wonderland Engine](https://wonderlandengine.com/). -Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors. +Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for sponsors of past years. From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations. **THANK YOU to all past and present supporters for helping to keep this project alive and thriving!** diff --git a/examples/example_allegro5/main.cpp b/examples/example_allegro5/main.cpp index 4fd379a3..ce55477c 100644 --- a/examples/example_allegro5/main.cpp +++ b/examples/example_allegro5/main.cpp @@ -69,8 +69,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. ALLEGRO_EVENT ev; while (al_get_next_event(queue, &ev)) diff --git a/examples/example_emscripten_opengl3/main.cpp b/examples/example_emscripten_opengl3/main.cpp index be338a83..24769283 100644 --- a/examples/example_emscripten_opengl3/main.cpp +++ b/examples/example_emscripten_opengl3/main.cpp @@ -111,8 +111,8 @@ static void main_loop(void* arg) // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_glfw_metal/main.mm b/examples/example_glfw_metal/main.mm index 2776ba2e..6e5966d6 100644 --- a/examples/example_glfw_metal/main.mm +++ b/examples/example_glfw_metal/main.mm @@ -88,8 +88,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index ee785b1f..e29d1829 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -80,8 +80,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index f8e8a02c..58c53fed 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -101,8 +101,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 2469be60..44b96268 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -467,8 +467,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index fed62b52..5e95fd62 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -94,8 +94,8 @@ void glut_display_func() } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. -// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. -// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. int main(int argc, char** argv) @@ -125,6 +125,7 @@ int main(int argc, char** argv) //ImGui::StyleColorsClassic(); // Setup Platform/Renderer backends + // FIXME: Consider reworking this example to install our own GLUT funcs + forward calls ImGui_ImplGLUT_XXX ones, instead of using ImGui_ImplGLUT_InstallFuncs(). ImGui_ImplGLUT_Init(); ImGui_ImplGLUT_InstallFuncs(); ImGui_ImplOpenGL2_Init(); diff --git a/examples/example_sdl_directx11/main.cpp b/examples/example_sdl_directx11/main.cpp index fc517152..3a5eea51 100644 --- a/examples/example_sdl_directx11/main.cpp +++ b/examples/example_sdl_directx11/main.cpp @@ -91,8 +91,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_sdl_metal/main.mm b/examples/example_sdl_metal/main.mm index caa86e64..e836b25b 100644 --- a/examples/example_sdl_metal/main.mm +++ b/examples/example_sdl_metal/main.mm @@ -88,8 +88,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_sdl_opengl2/main.cpp b/examples/example_sdl_opengl2/main.cpp index a81f8564..6e725f4c 100644 --- a/examples/example_sdl_opengl2/main.cpp +++ b/examples/example_sdl_opengl2/main.cpp @@ -79,8 +79,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_sdl_opengl3/main.cpp b/examples/example_sdl_opengl3/main.cpp index a7e7fc01..c6db5113 100644 --- a/examples/example_sdl_opengl3/main.cpp +++ b/examples/example_sdl_opengl3/main.cpp @@ -101,8 +101,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_sdl_sdlrenderer/main.cpp b/examples/example_sdl_sdlrenderer/main.cpp index 582b5a15..ef21c8f4 100644 --- a/examples/example_sdl_sdlrenderer/main.cpp +++ b/examples/example_sdl_sdlrenderer/main.cpp @@ -85,8 +85,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 9a26ae4f..866c1bfa 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -460,8 +460,8 @@ int main(int, char**) { // Poll and handle events (inputs, window resize, etc.) // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index ad88d1e9..c3726285 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -82,10 +82,7 @@ int main(int, char**) while (!done) { // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // See the WndProc() function below for our to dispatch events to the Win32 backend. MSG msg; while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { @@ -215,6 +212,10 @@ void CleanupRenderTarget() extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 7f1b4b89..8dc486a4 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -82,10 +82,7 @@ int main(int, char**) while (!done) { // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // See the WndProc() function below for our to dispatch events to the Win32 backend. MSG msg; while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { @@ -219,6 +216,10 @@ void CleanupRenderTarget() extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 74bfef32..6f6e680b 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -120,10 +120,7 @@ int main(int, char**) while (!done) { // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // See the WndProc() function below for our to dispatch events to the Win32 backend. MSG msg; while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { @@ -435,6 +432,10 @@ FrameContext* WaitForNextFrameResources() extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) diff --git a/examples/example_win32_directx9/main.cpp b/examples/example_win32_directx9/main.cpp index bdcd8b3e..9c454eeb 100644 --- a/examples/example_win32_directx9/main.cpp +++ b/examples/example_win32_directx9/main.cpp @@ -80,10 +80,7 @@ int main(int, char**) while (!done) { // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // See the WndProc() function below for our to dispatch events to the Win32 backend. MSG msg; while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { @@ -209,6 +206,10 @@ void ResetDevice() extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) From 6315716f23a8de4e08c29d8258142d1f7f209824 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Sat, 19 Feb 2022 10:22:24 +0200 Subject: [PATCH 03/17] Backends: Glut: Fix comparison operator precedence. --- backends/imgui_impl_glut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index d3e638b5..1bf036b5 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -269,7 +269,7 @@ void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y) if (glut_button == GLUT_LEFT_BUTTON) button = 0; if (glut_button == GLUT_RIGHT_BUTTON) button = 1; if (glut_button == GLUT_MIDDLE_BUTTON) button = 2; - if (button != -1 && state == GLUT_DOWN || state == GLUT_UP) + if (button != -1 && (state == GLUT_DOWN || state == GLUT_UP)) io.AddMouseButtonEvent(button, state == GLUT_DOWN); } From 0f14933577a1de01d90f8e87622296c466146f21 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 1 Mar 2022 18:45:41 +0100 Subject: [PATCH 04/17] Tables: Fixed incorrect border height used for logic when resizing one of several synchronized instance of a same table ID, when instances have a different height. (#3955, #3565) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 11 ++++++----- imgui_internal.h | 15 +++++++++++++-- imgui_tables.cpp | 22 +++++++++++++++------- imgui_widgets.cpp | 3 +++ 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 53ec7689..e3eb0278 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other Changes: clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822) - IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the return value is overriden by focus when gamepad/keyboard navigation is active. +- Tables: Fixed incorrect border height used for logic when resizing one of several synchronized + instance of a same table ID, when instances have a different height. (#3955). - Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate. - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Stack Tool: Added option to copy item path to clipboard. (#4631) diff --git a/imgui.cpp b/imgui.cpp index 196f0d19..87ec2784 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12173,19 +12173,20 @@ void ImGui::ShowMetricsWindow(bool* p_open) { static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n) { + ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); // Always using last submitted instance if (rect_type == TRT_OuterRect) { return table->OuterRect; } else if (rect_type == TRT_InnerRect) { return table->InnerRect; } else if (rect_type == TRT_WorkRect) { return table->WorkRect; } else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; } else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; } else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; } - else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); } + else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table_instance->LastOuterHeight); } else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); } else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; } - else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate - else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } - else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } - else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); } + else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); } // Note: y1/y2 not always accurate + else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); } + else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); } + else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); } IM_ASSERT(0); return ImRect(); } diff --git a/imgui_internal.h b/imgui_internal.h index 99cecc8d..9fd04d84 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -136,6 +136,7 @@ struct ImGuiTabBar; // Storage for a tab bar struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTable; // Storage for a table struct ImGuiTableColumn; // Storage for one column of a table +struct ImGuiTableInstanceData; // Storage for one instance of a same table struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings @@ -2290,6 +2291,15 @@ struct ImGuiTableCellData ImGuiTableColumnIdx Column; // Column number }; +// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs, does that needs they could be moved to ImGuiTableTempData ?) +struct ImGuiTableInstanceData +{ + float LastOuterHeight; // Outer height from last frame // FIXME: multi-instance issue (#3955) + float LastFirstRowHeight; // Height of first row from last frame // FIXME: possible multi-instance issue? + + ImGuiTableInstanceData() { LastOuterHeight = LastFirstRowHeight = 0.0f; } +}; + // FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData struct IMGUI_API ImGuiTable { @@ -2332,8 +2342,6 @@ struct IMGUI_API ImGuiTable float CellPaddingY; float CellSpacingX1; // Spacing between non-bordered cells float CellSpacingX2; - float LastOuterHeight; // Outer height from last frame - float LastFirstRowHeight; // Height of first row from last frame float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float ColumnsGivenWidth; // Sum of current column width float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window @@ -2353,6 +2361,8 @@ struct IMGUI_API ImGuiTable ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly + ImGuiTableInstanceData InstanceDataFirst; + ImVector InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good. ImGuiTableColumnSortSpecs SortSpecsSingle; ImVector SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good. ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() @@ -2708,6 +2718,7 @@ namespace ImGui IMGUI_API void TableDrawBorders(ImGuiTable* table); IMGUI_API void TableDrawContextMenu(ImGuiTable* table); IMGUI_API void TableMergeDrawChannels(ImGuiTable* table); + inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; } IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table); IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index def61f44..4abdf6de 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -361,6 +361,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->IsLayoutLocked = false; table->InnerWidth = inner_width; temp_data->UserOuterSize = outer_size; + if (instance_no > 0 && table->InstanceDataExtra.Size < instance_no) + table->InstanceDataExtra.push_back(ImGuiTableInstanceData()); // When not using a child window, WorkRect.Max will grow as we append contents. if (use_child_window) @@ -933,9 +935,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) width_remaining_for_stretched_columns -= 1.0f; } + ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); table->HoveredColumnBody = -1; table->HoveredColumnBorder = -1; - const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight)); + const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table_instance->LastOuterHeight)); const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0); // [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column @@ -1096,7 +1099,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 10] Hit testing on borders if (table->Flags & ImGuiTableFlags_Resizable) TableUpdateBorders(table); - table->LastFirstRowHeight = 0.0f; + table_instance->LastFirstRowHeight = 0.0f; table->IsLayoutLocked = true; table->IsUsingHeaders = false; @@ -1141,10 +1144,11 @@ void ImGui::TableUpdateBorders(ImGuiTable* table) // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height). // Actual columns highlight/render will be performed in EndTable() and not be affected. + ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; const float hit_y1 = table->OuterRect.Min.y; - const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight); - const float hit_y2_head = hit_y1 + table->LastFirstRowHeight; + const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight); + const float hit_y2_head = hit_y1 + table_instance->LastFirstRowHeight; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { @@ -1223,6 +1227,7 @@ void ImGui::EndTable() TableOpenContextMenu((int)table->HoveredColumnBody); // Finalize table height + ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize; inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize; inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos; @@ -1233,7 +1238,7 @@ void ImGui::EndTable() else if (!(flags & ImGuiTableFlags_NoHostExtendY)) table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); - table->LastOuterHeight = table->OuterRect.GetHeight(); + table_instance->LastOuterHeight = table->OuterRect.GetHeight(); // Setup inner scrolling range // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, @@ -1749,7 +1754,7 @@ void ImGui::TableEndRow(ImGuiTable* table) const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount); const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest); if (table->CurrentRow == 0) - table->LastFirstRowHeight = bg_y2 - bg_y1; + TableGetInstanceData(table, table->InstanceCurrent)->LastFirstRowHeight = bg_y2 - bg_y1; const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y); if (is_visible) @@ -2502,10 +2507,11 @@ void ImGui::TableDrawBorders(ImGuiTable* table) inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); // Draw inner border and resizing feedback + ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float border_size = TABLE_BORDER_SIZE; const float draw_y1 = table->InnerRect.Min.y; const float draw_y2_body = table->InnerRect.Max.y; - const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1; + const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1; if (table->Flags & ImGuiTableFlags_BordersInnerV) { for (int order_n = 0; order_n < table->ColumnsCount; order_n++) @@ -3536,6 +3542,8 @@ void ImGui::DebugNodeTable(ImGuiTable* table) GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255)); if (!open) return; + if (table->InstanceCurrent > 0) + ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); bool clear_settings = SmallButton("Clear settings"); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 64e7aa9c..86229b21 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3533,6 +3533,9 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f // - InputText() // - InputTextWithHint() // - InputTextMultiline() +// - InputTextGetCharInfo() [Internal] +// - InputTextReindexLines() [Internal] +// - InputTextReindexLinesRange() [Internal] // - InputTextEx() [Internal] //------------------------------------------------------------------------- From 3deb92c2c58295c904a046fd892b8845c8cac7e9 Mon Sep 17 00:00:00 2001 From: jakubtomsu Date: Sun, 13 Mar 2022 12:47:14 +0700 Subject: [PATCH 05/17] Add IMGUI_STB_SPRINTF_FILENAME to support custom stb_printf.h include path (#5068, #2954) --- docs/CHANGELOG.txt | 1 + imconfig.h | 7 ++++--- imgui.cpp | 4 ++++ imgui_draw.cpp | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e3eb0278..547922d2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Stack Tool: Added option to copy item path to clipboard. (#4631) - Misc: Fixed IsAnyItemHovered() returning false when using navigation. +- Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] diff --git a/imconfig.h b/imconfig.h index c854832e..9a2aca4b 100644 --- a/imconfig.h +++ b/imconfig.h @@ -62,12 +62,13 @@ // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" +//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) -// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of 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 +//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) +// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. +//#define IMGUI_USE_STB_SPRINTF //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). diff --git a/imgui.cpp b/imgui.cpp index 87ec2784..d53653d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1639,8 +1639,12 @@ const char* ImStrSkipBlank(const char* str) // designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) #ifdef IMGUI_USE_STB_SPRINTF #define STB_SPRINTF_IMPLEMENTATION +#ifdef IMGUI_STB_SPRINTF_FILENAME +#include IMGUI_STB_SPRINTF_FILENAME +#else #include "stb_sprintf.h" #endif +#endif #if defined(_MSC_VER) && !defined(vsnprintf) #define vsnprintf _vsnprintf diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 23938706..47a4e8fc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -90,7 +90,7 @@ Index of this file: #endif //------------------------------------------------------------------------- -// [SECTION] STB libraries implementation +// [SECTION] STB libraries implementation (for stb_truetype and stb_rect_pack) //------------------------------------------------------------------------- // Compile time options: From 279db558402a5d458b135c1e131b9d5de757afae Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 13 Mar 2022 12:58:40 +0700 Subject: [PATCH 06/17] Updated stb_rect_pack.h from 1.00 to 1.01. (#5075) (our STBRP__CDECL change was merged) --- docs/CHANGELOG.txt | 1 + imgui_draw.cpp | 4 ++-- imstb_rectpack.h | 42 +++++++++++++++--------------------------- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 547922d2..96736215 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,7 @@ Other Changes: - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] +- Misc: Updated stb_rect_pack.h from 1.00 to 1.01. (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] - Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 47a4e8fc..10f670c2 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2637,8 +2637,8 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa for (int i = 0; i < pack_rects.Size; i++) if (pack_rects[i].was_packed) { - user_rects[i].X = pack_rects[i].x; - user_rects[i].Y = pack_rects[i].y; + user_rects[i].X = (unsigned short)pack_rects[i].x; + user_rects[i].Y = (unsigned short)pack_rects[i].y; IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); } diff --git a/imstb_rectpack.h b/imstb_rectpack.h index 39589521..f6917e7a 100644 --- a/imstb_rectpack.h +++ b/imstb_rectpack.h @@ -1,15 +1,19 @@ // [DEAR IMGUI] -// This is a slightly modified version of stb_rect_pack.h 1.00. -// Those changes would need to be pushed into nothings/stb: -// - Added STBRP__CDECL +// This is a slightly modified version of stb_rect_pack.h 1.01. // Grep for [DEAR IMGUI] to find the changes. - -// stb_rect_pack.h - v1.00 - public domain - rectangle packing +// +// stb_rect_pack.h - v1.01 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. // Does not do rotation. // +// Before #including, +// +// #define STB_RECT_PACK_IMPLEMENTATION +// +// in the file that you want to have the implementation. +// // Not necessarily the awesomest packing method, but better than // the totally naive one in stb_truetype (which is primarily what // this is meant to replace). @@ -41,6 +45,7 @@ // // Version history: // +// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 0.99 (2019-02-07) warning fixes // 0.11 (2017-03-03) return packing success/fail result @@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context; typedef struct stbrp_node stbrp_node; typedef struct stbrp_rect stbrp_rect; -#ifdef STBRP_LARGE_RECTS typedef int stbrp_coord; -#else -typedef unsigned short stbrp_coord; -#endif + +#define STBRP__MAXVAL 0x7fffffff +// Mostly for internal use, but this is the maximum supported coordinate value. STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type @@ -213,10 +217,9 @@ struct stbrp_context #define STBRP_ASSERT assert #endif -// [DEAR IMGUI] Added STBRP__CDECL #ifdef _MSC_VER #define STBRP__NOTUSED(v) (void)(v) -#define STBRP__CDECL __cdecl +#define STBRP__CDECL __cdecl #else #define STBRP__NOTUSED(v) (void)sizeof(v) #define STBRP__CDECL @@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) { int i; -#ifndef STBRP_LARGE_RECTS - STBRP_ASSERT(width <= 0xffff && height <= 0xffff); -#endif for (i=0; i < num_nodes-1; ++i) nodes[i].next = &nodes[i+1]; @@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, context->extra[0].y = 0; context->extra[0].next = &context->extra[1]; context->extra[1].x = (stbrp_coord) width; -#ifdef STBRP_LARGE_RECTS context->extra[1].y = (1<<30); -#else - context->extra[1].y = 65535; -#endif context->extra[1].next = NULL; } @@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt if (y <= best_y) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { best_x = xpos; - STBRP_ASSERT(y <= best_y); + //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] best_y = y; best_waste = waste; best = prev; @@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i return res; } -// [DEAR IMGUI] Added STBRP__CDECL static int STBRP__CDECL rect_height_compare(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; @@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b) return (p->w > q->w) ? -1 : (p->w < q->w); } -// [DEAR IMGUI] Added STBRP__CDECL static int STBRP__CDECL rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; @@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b) return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); } -#ifdef STBRP_LARGE_RECTS -#define STBRP__MAXVAL 0xffffffff -#else -#define STBRP__MAXVAL 0xffff -#endif - STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { int i, all_rects_packed = 1; From de451d447420783f3bdc5567fe6f35e7b177d101 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 13 Mar 2022 13:02:56 +0700 Subject: [PATCH 07/17] Updated stb_textedit.h from 1.13 to 1.14. (#5075) (Our pageup/pagedown PR was merged, so this is essentially a no-op) --- docs/CHANGELOG.txt | 3 ++- imstb_textedit.h | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 96736215..a439feca 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,7 +63,8 @@ Other Changes: - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] -- Misc: Updated stb_rect_pack.h from 1.00 to 1.01. (#5075) +- Misc: Updated stb_textedit.h from 1.13 to 1.14 (our changes so this effectively is a no-op). (#5075) +- Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] - Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd] diff --git a/imstb_textedit.h b/imstb_textedit.h index 2c635b27..75a159da 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -1,10 +1,10 @@ // [DEAR IMGUI] -// This is a slightly modified version of stb_textedit.h 1.13. +// This is a slightly modified version of stb_textedit.h 1.14. // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // Grep for [DEAR IMGUI] to find the changes. -// stb_textedit.h - v1.13 - public domain - Sean Barrett +// stb_textedit.h - v1.14 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing @@ -35,6 +35,7 @@ // // VERSION HISTORY // +// 1.14 (2021-07-11) page up/down, various fixes // 1.13 (2019-02-07) fix bug in undo size management // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield @@ -58,6 +59,7 @@ // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 +// Louis Schnellbach: page up/down in 1.14 // // Bugfixes: // Scott Graham @@ -93,8 +95,8 @@ // moderate sizes. The undo system does no memory allocations, so // it grows STB_TexteditState by the worst-case storage which is (in bytes): // -// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT -// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT +// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT +// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT // // // Implementation mode: @@ -716,10 +718,6 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta state->has_preferred_x = 0; return 1; } - // [DEAR IMGUI] - //// remove the undo since we didn't actually insert the characters - //if (state->undostate.undo_point) - // --state->undostate.undo_point; // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) return 0; } From 0cff5ac5a1955a8ed9adc37fd13e15011966569a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 13 Mar 2022 17:49:37 +0700 Subject: [PATCH 08/17] Updated stb_textedit.h from 1.20 to 1.26 (many fixes). (#5075) --- docs/CHANGELOG.txt | 1 + imstb_truetype.h | 819 +++++++++++++++++++++++++++------------------ 2 files changed, 500 insertions(+), 320 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a439feca..2ba63c40 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,7 @@ Other Changes: - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] +- Misc: Updated stb_truetype.h from 1.20 to 1.26 (many fixes). (#5075) - Misc: Updated stb_textedit.h from 1.13 to 1.14 (our changes so this effectively is a no-op). (#5075) - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] diff --git a/imstb_truetype.h b/imstb_truetype.h index 48c20261..bd143556 100644 --- a/imstb_truetype.h +++ b/imstb_truetype.h @@ -1,10 +1,19 @@ // [DEAR IMGUI] -// This is a slightly modified version of stb_truetype.h 1.20. +// This is a slightly modified version of stb_truetype.h 1.26. // Mostly fixing for compiler and static analyzer warnings. // Grep for [DEAR IMGUI] to find the changes. -// stb_truetype.h - v1.20 - public domain -// authored from 2009-2016 by Sean Barrett / RAD Game Tools +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= // // This library processes TrueType files: // parse files @@ -37,11 +46,11 @@ // Daniel Ribeiro Maciel // // Bug/warning reports/fixes: -// "Zer" on mollyrocket Fabian "ryg" Giesen -// Cass Everitt Martins Mozeiko -// stoiko (Haemimont Games) Cap Petschulat -// Brian Hook Omar Cornut -// Walter van Niftrik github:aloucks +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege // David Gow Peter LaValle // David Given Sergey Popov // Ivan-Assen Ivanov Giumo X. Clanjor @@ -49,11 +58,17 @@ // Johan Duparc Thomas Fields // Hou Qiming Derek Vinyard // Rob Loach Cort Stratton -// Kenney Phillis Jr. github:oyvindjam -// Brian Costabile github:vassvik +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) // // VERSION HISTORY // +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod // 1.18 (2018-01-29) add missing function @@ -248,19 +263,6 @@ // recommend it. // // -// SOURCE STATISTICS (based on v0.6c, 2050 LOC) -// -// Documentation & header file 520 LOC \___ 660 LOC documentation -// Sample code 140 LOC / -// Truetype parsing 620 LOC ---- 620 LOC TrueType -// Software rasterization 240 LOC \. -// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation -// Bitmap management 100 LOC / -// Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 -// C runtime library abstraction 60 LOC ---- 60 -// -// // PERFORMANCE MEASUREMENTS FOR 1.06: // // 32-bit 64-bit @@ -275,8 +277,8 @@ //// SAMPLE PROGRAMS //// // -// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless -// +// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless. +// See "tests/truetype_demo_win32.c" for a complete version. #if 0 #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #include "stb_truetype.h" @@ -302,6 +304,8 @@ void my_stbtt_initfont(void) void my_stbtt_print(float x, float y, char *text) { // assume orthographic projection with units = screen pixels, origin at top left + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ftex); glBegin(GL_QUADS); @@ -309,10 +313,10 @@ void my_stbtt_print(float x, float y, char *text) if (*text >= 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } ++text; } @@ -719,7 +723,7 @@ struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph @@ -802,6 +806,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // @@ -846,6 +862,12 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + ////////////////////////////////////////////////////////////////////////////// // // BITMAP RENDERING @@ -1347,6 +1369,22 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) return stbtt__cff_get_index(&cff); } +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { stbtt_uint32 cmap, t; @@ -1426,6 +1464,8 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in else info->numGlyphs = 0xffff; + info->svg = -1; + // find a cmap encoding table we understand *now* to avoid searching // later. (todo: could make this installable) // the same regardless of glyph. @@ -1509,12 +1549,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep search += 2; { - stbtt_uint16 offset, start; + stbtt_uint16 offset, start, last; stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) return 0; offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); @@ -1774,7 +1814,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s } } num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { + } else if (numberOfContours < 0) { // Compound shapes. int more = 1; stbtt_uint8 *comp = data + g + 10; @@ -1841,7 +1881,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s if (comp_verts) STBTT_free(comp_verts, info->userdata); return 0; } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595 + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); if (vertices) STBTT_free(vertices, info->userdata); vertices = tmp; @@ -1851,9 +1891,6 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s // More components ? more = flags & (1<<5); } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); } else { // numberOfCounters == 0, do nothing } @@ -2107,7 +2144,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); has_subrs = 1; } - // fallthrough + // FALLTHROUGH case 0x1D: // callgsubr if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); v = (int) s[--sp]; @@ -2212,7 +2249,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st } break; default: - if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560 + if (b0 != 255 && b0 != 28 && b0 < 32) return STBTT__CSERR("reserved operator"); // push immediate @@ -2282,7 +2319,49 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -2312,245 +2391,225 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph return 0; } -static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) -{ - stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); - switch(coverageFormat) { - case 1: { - stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); - - // Binary search. - stbtt_int32 l=0, r=glyphCount-1, m; - int straw, needle=glyph; - while (l <= r) { - stbtt_uint8 *glyphArray = coverageTable + 4; - stbtt_uint16 glyphID; - m = (l + r) >> 1; - glyphID = ttUSHORT(glyphArray + 2 * m); - straw = glyphID; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - return m; - } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; } - } break; - - case 2: { - stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); - stbtt_uint8 *rangeArray = coverageTable + 4; - - // Binary search. - stbtt_int32 l=0, r=rangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *rangeRecord; - m = (l + r) >> 1; - rangeRecord = rangeArray + 6 * m; - strawStart = ttUSHORT(rangeRecord); - strawEnd = ttUSHORT(rangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else { - stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); - return startCoverageIndex + glyph - strawStart; - } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; } - } break; + } + break; + } - default: { - // There are no other cases. - STBTT_assert(0); - } break; - } + default: return -1; // unsupported + } - return -1; + return -1; } static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) { - stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); - switch(classDefFormat) - { - case 1: { - stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); - stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); - stbtt_uint8 *classDef1ValueArray = classDefTable + 6; - - if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) - return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); - - // [DEAR IMGUI] Commented to fix static analyzer warning - //classDefTable = classDef1ValueArray + 2 * glyphCount; - } break; - - case 2: { - stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); - stbtt_uint8 *classRangeRecords = classDefTable + 4; - - // Binary search. - stbtt_int32 l=0, r=classRangeCount-1, m; - int strawStart, strawEnd, needle=glyph; - while (l <= r) { - stbtt_uint8 *classRangeRecord; - m = (l + r) >> 1; - classRangeRecord = classRangeRecords + 6 * m; - strawStart = ttUSHORT(classRangeRecord); - strawEnd = ttUSHORT(classRangeRecord + 2); - if (needle < strawStart) - r = m - 1; - else if (needle > strawEnd) - l = m + 1; - else - return (stbtt_int32)ttUSHORT(classRangeRecord + 4); - } + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; - // [DEAR IMGUI] Commented to fix static analyzer warning - //classDefTable = classRangeRecords + 6 * classRangeCount; - } break; + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } - default: { - // There are no other cases. - STBTT_assert(0); - } break; - } + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } - return -1; + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; } // Define to STBTT_assert(x) if you want to break on unimplemented formats. #define STBTT_GPOS_TODO_assert(x) -static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) -{ - stbtt_uint16 lookupListOffset; - stbtt_uint8 *lookupList; - stbtt_uint16 lookupCount; - stbtt_uint8 *data; - stbtt_int32 i; - - if (!info->gpos) return 0; - - data = info->data + info->gpos; - - if (ttUSHORT(data+0) != 1) return 0; // Major version 1 - if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 - - lookupListOffset = ttUSHORT(data+8); - lookupList = data + lookupListOffset; - lookupCount = ttUSHORT(lookupList); - - for (i=0; i> 1; - pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; - secondGlyph = ttUSHORT(pairValue); - straw = secondGlyph; - if (needle < straw) - r = m - 1; - else if (needle > straw) - l = m + 1; - else { - stbtt_int16 xAdvance = ttSHORT(pairValue + 2); - return xAdvance; - } - } - } break; - - case 2: { - stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); - stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); - - stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); - stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); - int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); - int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); - - stbtt_uint16 class1Count = ttUSHORT(table + 12); - stbtt_uint16 class2Count = ttUSHORT(table + 14); - STBTT_assert(glyph1class < class1Count); - STBTT_assert(glyph2class < class2Count); - - // TODO: Support more formats. - STBTT_GPOS_TODO_assert(valueFormat1 == 4); - if (valueFormat1 != 4) return 0; - STBTT_GPOS_TODO_assert(valueFormat2 == 0); - if (valueFormat2 != 0) return 0; - - if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { - stbtt_uint8 *class1Records = table + 16; - stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); - stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); - return xAdvance; - } - } break; - - default: { - // There are no other cases. - STBTT_assert(0); - break; - } // [DEAR IMGUI] removed ; - } - } - break; - } // [DEAR IMGUI] removed ; +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } default: - // TODO: Implement other stuff. - break; - } - } + return 0; // Unsupported position format + } + } + } - return 0; + return 0; } STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) @@ -2559,8 +2618,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int if (info->gpos) xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); - - if (info->kern) + else if (info->kern) xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); return xAdvance; @@ -2621,6 +2679,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_free(v, info->userdata); } +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + ////////////////////////////////////////////////////////////////////////////// // // antialiasing software rasterizer @@ -2970,6 +3067,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg } } +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) { float y_bottom = y_top+1; @@ -3024,13 +3138,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, float height; // simple case, only spans one pixel int x = (int) x_top; - height = sy1 - sy0; + height = (sy1 - sy0) * e->direction; STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled } else { int x,x1,x2; - float y_crossing, step, sign, area; + float y_crossing, y_final, step, sign, area; // covers 2+ pixels if (x_top > x_bottom) { // flip scanline vertically; signed area is the same @@ -3042,32 +3156,80 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, dx = -dx; dy = -dy; t = x0, x0 = xb, xb = t; - // [DEAR IMGUI] Fix static analyzer warning - (void)dx; // [ImGui: fix static analyzer warning] } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); x1 = (int) x_top; x2 = (int) x_bottom; // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; sign = e->direction; - // area of the rectangle covered from y0..y_crossing + + // area of the rectangle covered from sy0..y_crossing area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - step = sign * dy; + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 area += step; } - y_crossing += dy * (x2 - (x1+1)); - - STBTT_assert(STBTT_fabs(area) <= 1.01f); + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); - scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + // the rest of the line is filled based on the total height of the line segment in this pixel scanline_fill[x2] += sign * (sy1-sy0); } } else { @@ -3075,6 +3237,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // clipping logic. since this does not match the intended use // of this library, we use a different, very slow brute // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box int x; for (x=0; x < len; ++x) { // cases: @@ -3989,6 +4154,7 @@ static float stbtt__oversample_shift(int oversample) STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k; + int missing_glyph_added = 0; k=0; for (i=0; i < num_ranges; ++i) { @@ -4000,7 +4166,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); - if (glyph == 0 && spc->skip_missing) { + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { rects[k].w = rects[k].h = 0; } else { stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, @@ -4010,6 +4176,8 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb &x0,&y0,&x1,&y1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; } ++k; } @@ -4044,7 +4212,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { - int i,j,k, return_value = 1; + int i,j,k, missing_glyph = -1, return_value = 1; // save current values int old_h_over = spc->h_oversample; @@ -4109,6 +4277,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const bc->yoff = (float) y0 * recip_v + sub_y; bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; } else { return_value = 0; // if any fail, report failure } @@ -4132,7 +4307,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; - int i,j,n, return_value; // [DEAR IMGUI] removed = 1 + int i, j, n, return_value; // [DEAR IMGUI] removed = 1; //stbrp_context *context = (stbrp_context *) spc->pack_info; stbrp_rect *rects; @@ -4301,15 +4476,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex float y_frac; int winding = 0; - orig[0] = x; - //orig[1] = y; // [DEAR IMGUI] commented double assignment - // make sure y never passes through a vertex of the shape y_frac = (float) STBTT_fmod(y, 1.0f); if (y_frac < 0.01f) y += 0.01f; else if (y_frac > 0.99f) y -= 0.01f; + + orig[0] = x; orig[1] = y; // test a ray from (-infinity,y) to (x,y) @@ -4371,35 +4545,35 @@ static float stbtt__cuberoot( float x ) return (float) STBTT_pow( x,1.0f/3.0f); } -// x^3 + c*x^2 + b*x + a = 0 +// x^3 + a*x^2 + b*x + c = 0 static int stbtt__solve_cubic(float a, float b, float c, float* r) { - float s = -a / 3; - float p = b - a*a / 3; - float q = a * (2*a*a - 9*b) / 27 + c; + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; float p3 = p*p*p; - float d = q*q + 4*p3 / 27; - if (d >= 0) { - float z = (float) STBTT_sqrt(d); - float u = (-q + z) / 2; - float v = (-q - z) / 2; - u = stbtt__cuberoot(u); - v = stbtt__cuberoot(v); - r[0] = s + u + v; - return 1; - } else { - float u = (float) STBTT_sqrt(-p/3); - float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative - float m = (float) STBTT_cos(v); + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; - r[0] = s + u * 2 * m; - r[1] = s - u * (m + n); - r[2] = s - u * (m - n); + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); - return 3; + return 3; } } @@ -4410,12 +4584,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc int w,h; unsigned char *data; - // if one scale is 0, use same scale for both - if (scale_x == 0) scale_x = scale_y; - if (scale_y == 0) { - if (scale_x == 0) return NULL; // if both scales are 0, return NULL - scale_y = scale_x; - } + if (scale == 0) return NULL; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); @@ -4481,18 +4650,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc for (i=0; i < num_verts; ++i) { float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; - // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve - float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); - if (dist2 < min_dist*min_dist) - min_dist = (float) STBTT_sqrt(dist2); - - if (verts[i].type == STBTT_vline) { + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + // coarse culling against bbox //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) - float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; STBTT_assert(i != 0); if (dist < min_dist) { // check position along line @@ -4519,7 +4687,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc float ax = x1-x0, ay = y1-y0; float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; float mx = x0 - sx, my = y0 - sy; - float res[3],px,py,t,it; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; float a_inv = precompute[i]; if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula float a = 3*(ax*bx + ay*by); @@ -4546,6 +4715,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc float d = (mx*ax+my*ay) * a_inv; num = stbtt__solve_cubic(b, c, d, res); } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { t = res[0], it = 1.0f - t; px = it*it*x0 + 2*t*it*x1 + t*t*x2; @@ -4805,6 +4978,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod // 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix From fd06ed833be6a4ac9a99c0383ca014011535c246 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 13 Mar 2022 13:15:32 +0700 Subject: [PATCH 09/17] Misc: tweaks + fix warnings on backends withtout -wno-memaccess (#4995, #5104) --- backends/imgui_impl_allegro5.cpp | 2 +- backends/imgui_impl_dx10.cpp | 2 +- backends/imgui_impl_dx11.cpp | 2 +- backends/imgui_impl_dx12.cpp | 2 +- backends/imgui_impl_dx9.cpp | 2 +- backends/imgui_impl_glfw.cpp | 2 +- backends/imgui_impl_opengl2.cpp | 2 +- backends/imgui_impl_opengl3.cpp | 2 +- backends/imgui_impl_sdl.cpp | 2 +- backends/imgui_impl_sdlrenderer.cpp | 2 +- backends/imgui_impl_vulkan.cpp | 2 +- backends/imgui_impl_vulkan.h | 2 +- backends/imgui_impl_win32.cpp | 2 +- imgui.cpp | 1 - imgui.h | 8 ++++---- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 3 +-- misc/freetype/imgui_freetype.cpp | 2 +- 20 files changed, 23 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 542fe129..3797402b 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -71,7 +71,7 @@ struct ImGui_ImplAllegro5_Data ALLEGRO_VERTEX_DECL* VertexDecl; char* ClipboardTextData; - ImGui_ImplAllegro5_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplAllegro5_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 79bf731d..09e01987 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -59,7 +59,7 @@ struct ImGui_ImplDX10_Data int VertexBufferSize; int IndexBufferSize; - ImGui_ImplDX10_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } + ImGui_ImplDX10_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; struct VERTEX_CONSTANT_BUFFER diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 3f628cbc..a7407d66 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -60,7 +60,7 @@ struct ImGui_ImplDX11_Data int VertexBufferSize; int IndexBufferSize; - ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } + ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; struct VERTEX_CONSTANT_BUFFER diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index e9d2e961..6b9d29ec 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -71,7 +71,7 @@ struct ImGui_ImplDX12_Data UINT numFramesInFlight; UINT frameIndex; - ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } + ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; } }; struct VERTEX_CONSTANT_BUFFER diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp index 4cbd7959..6aca8a9f 100644 --- a/backends/imgui_impl_dx9.cpp +++ b/backends/imgui_impl_dx9.cpp @@ -46,7 +46,7 @@ struct ImGui_ImplDX9_Data int VertexBufferSize; int IndexBufferSize; - ImGui_ImplDX9_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } + ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; struct CUSTOMVERTEX diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 516aa3c2..6cdf7494 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -105,7 +105,7 @@ struct ImGui_ImplGlfw_Data GLFWcharfun PrevUserCallbackChar; GLFWmonitorfun PrevUserCallbackMonitor; - ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 17a6faeb..6b135bc5 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -61,7 +61,7 @@ struct ImGui_ImplOpenGL2_Data { GLuint FontTexture; - ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 0d3489ce..8f800f30 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -193,7 +193,7 @@ struct ImGui_ImplOpenGL3_Data GLsizeiptr IndexBufferSize; bool HasClipOrigin; - ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index ef5ef609..223ce158 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -87,7 +87,7 @@ struct ImGui_ImplSDL2_Data char* ClipboardTextData; bool MouseCanUseGlobalState; - ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_sdlrenderer.cpp b/backends/imgui_impl_sdlrenderer.cpp index 8d20b043..8a54567b 100644 --- a/backends/imgui_impl_sdlrenderer.cpp +++ b/backends/imgui_impl_sdlrenderer.cpp @@ -42,7 +42,7 @@ struct ImGui_ImplSDLRenderer_Data { SDL_Renderer* SDLRenderer; SDL_Texture* FontTexture; - ImGui_ImplSDLRenderer_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplSDLRenderer_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index dbd8b184..a4bddc07 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -118,7 +118,7 @@ struct ImGui_ImplVulkan_Data ImGui_ImplVulkan_Data() { - memset(this, 0, sizeof(*this)); + memset((void*)this, 0, sizeof(*this)); BufferMemoryAlignment = 256; } }; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index d80bfc4e..f2f3e345 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -147,7 +147,7 @@ struct ImGui_ImplVulkanH_Window ImGui_ImplVulkanH_Window() { - memset(this, 0, sizeof(*this)); + memset((void*)this, 0, sizeof(*this)); PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; ClearEnable = true; } diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index ee951fc7..8977a1f6 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -94,7 +94,7 @@ struct ImGui_ImplWin32_Data PFN_XInputGetState XInputGetState; #endif - ImGui_ImplWin32_Data() { memset(this, 0, sizeof(*this)); } + ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts diff --git a/imgui.cpp b/imgui.cpp index d53653d9..a7cbfb82 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8069,7 +8069,6 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi IM_ASSERT(window->IsFallbackWindow); break; } - IM_ASSERT(window == g.CurrentWindow); if (window->Flags & ImGuiWindowFlags_ChildWindow) { if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name); diff --git a/imgui.h b/imgui.h index 20e1bfcf..7fc4ba68 100644 --- a/imgui.h +++ b/imgui.h @@ -2342,13 +2342,13 @@ struct ImGuiListClipper // **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed. struct ImColor { - ImVec4 Value; + ImVec4 Value; - ImColor() { Value.x = Value.y = Value.z = Value.w = 0.0f; } + constexpr ImColor() { } + constexpr ImColor(float r, float g, float b, float a = 1.0f) : Value(r, g, b, a) { } + constexpr ImColor(const ImVec4& col) : Value(col) {} ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f / 255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; } ImColor(ImU32 rgba) { float sc = 1.0f / 255.0f; Value.x = (float)((rgba >> IM_COL32_R_SHIFT) & 0xFF) * sc; Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; } - ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; } - ImColor(const ImVec4& col) { Value = col; } inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } inline operator ImVec4() const { return Value; } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fc2f4cce..5f9742d1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3873,7 +3873,7 @@ static void ShowDemoWindowTables() sprintf(buf, "Hello %d,%d", column, row); if (contents_type == CT_Text) ImGui::TextUnformatted(buf); - else if (contents_type) + else if (contents_type == CT_FillButton) ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); } } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 10f670c2..e9197586 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3878,7 +3878,7 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im draw_list->PathFillConvex(col); } -void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding) +void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding) { const bool fill_L = (inner.Min.x > outer.Min.x); const bool fill_R = (inner.Max.x < outer.Max.x); diff --git a/imgui_internal.h b/imgui_internal.h index 9fd04d84..75092ccf 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -232,7 +232,7 @@ namespace ImStb #define IM_NEWLINE "\n" #endif #define IM_TABSIZE (4) -#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 +#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds @@ -2782,7 +2782,7 @@ namespace ImGui IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); - IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding); + IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 86229b21..407ae51c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -843,9 +843,8 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) // Render ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImVec2 center = bb.GetCenter(); if (hovered || held) - window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12); + window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12); RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); // Switch to moving the window after mouse is moved beyond the initial drag threshold diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index a72ec8c8..4066a9a6 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -368,7 +368,7 @@ struct ImFontBuildSrcGlyphFT uint32_t Codepoint; unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array - ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); } + ImFontBuildSrcGlyphFT() { memset((void*)this, 0, sizeof(*this)); } }; struct ImFontBuildSrcDataFT From 28ba54a32ae604f57430ee311dc5b1d1aeeaa4ca Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 14 Mar 2022 10:23:30 +0700 Subject: [PATCH 10/17] Internals: add AddSettingsHandler(), RemoveSettingsHandler(). --- imgui.cpp | 18 ++++++++++++++++-- imgui.h | 2 +- imgui_internal.h | 4 +++- imgui_tables.cpp | 5 ++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a7cbfb82..0949f430 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4479,11 +4479,11 @@ void ImGui::Initialize(ImGuiContext* context) ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine; ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll; ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll; - g.SettingsHandlers.push_back(ini_handler); + AddSettingsHandler(&ini_handler); } // Add .ini handle for ImGuiTable type - TableSettingsInstallHandler(context); + TableSettingsAddSettingsHandler(); // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); @@ -11618,6 +11618,20 @@ ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name) return CreateNewWindowSettings(name); } +void ImGui::AddSettingsHandler(const ImGuiSettingsHandler* handler) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL); + g.SettingsHandlers.push_back(*handler); +} + +void ImGui::RemoveSettingsHandler(const char* type_name) +{ + ImGuiContext& g = *GImGui; + if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name)) + g.SettingsHandlers.erase(handler); +} + ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 7fc4ba68..f92c70dc 100644 --- a/imgui.h +++ b/imgui.h @@ -65,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.88 WIP" -#define IMGUI_VERSION_NUM 18709 +#define IMGUI_VERSION_NUM 18710 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_internal.h b/imgui_internal.h index 75092ccf..8cf412ba 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2541,6 +2541,8 @@ namespace ImGui IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name); + IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler); + IMGUI_API void RemoveSettingsHandler(const char* type_name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); // Scrolling @@ -2744,7 +2746,7 @@ namespace ImGui IMGUI_API void TableSaveSettings(ImGuiTable* table); IMGUI_API void TableResetSettings(ImGuiTable* table); IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table); - IMGUI_API void TableSettingsInstallHandler(ImGuiContext* context); + IMGUI_API void TableSettingsAddSettingsHandler(); IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count); IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 4abdf6de..98730a2b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3433,9 +3433,8 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle } } -void ImGui::TableSettingsInstallHandler(ImGuiContext* context) +void ImGui::TableSettingsAddSettingsHandler() { - ImGuiContext& g = *context; ImGuiSettingsHandler ini_handler; ini_handler.TypeName = "Table"; ini_handler.TypeHash = ImHashStr("Table"); @@ -3444,7 +3443,7 @@ void ImGui::TableSettingsInstallHandler(ImGuiContext* context) ini_handler.ReadLineFn = TableSettingsHandler_ReadLine; ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll; ini_handler.WriteAllFn = TableSettingsHandler_WriteAll; - g.SettingsHandlers.push_back(ini_handler); + AddSettingsHandler(&ini_handler); } //------------------------------------------------------------------------- From 6fae29679a8f9b163f6ef11bd643c4aa859cc31b Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 15 Mar 2022 18:32:49 +0700 Subject: [PATCH 11/17] Examples: Emscripten: Fix build. (#3632) --- docs/CHANGELOG.txt | 3 ++- examples/example_emscripten_wgpu/main.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2ba63c40..1fee6e0e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,7 @@ Other Changes: - Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate. - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Stack Tool: Added option to copy item path to clipboard. (#4631) +- Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd] - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] @@ -68,7 +69,7 @@ Other Changes: - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] -- Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd] +- Examples: Emscripten: Fix building for latest Emscripten specs. (#3632) ----------------------------------------------------------------------- diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index d11d906c..6a63db26 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -217,7 +217,7 @@ static void main_loop(void* window) WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc); ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass); - wgpuRenderPassEncoderEndPass(pass); + wgpuRenderPassEncoderEnd(pass); WGPUCommandBufferDescriptor cmd_buffer_desc = {}; WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); From 31e77eacdb93e713730587ec26b7d20e1fd8e224 Mon Sep 17 00:00:00 2001 From: Sergiu Giurgiu Date: Sat, 19 Mar 2022 19:13:31 -0400 Subject: [PATCH 12/17] Backends: SDL: Add extra mouse buttons handling (#5125) --- backends/imgui_impl_sdl.cpp | 3 +++ docs/CHANGELOG.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 223ce158..b314dbb9 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,6 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). // 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer. // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. @@ -267,6 +268,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; } + if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; } + if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; } if (mouse_button == -1) break; io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN)); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1fee6e0e..54d22d7f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,6 +69,7 @@ Other Changes: - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] +- Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Examples: Emscripten: Fix building for latest Emscripten specs. (#3632) From 7602277c8692e33ac7fa89bc9c0e66c3530b246b Mon Sep 17 00:00:00 2001 From: Wvader <34067397+wvader@users.noreply.github.com> Date: Sat, 19 Mar 2022 16:33:56 +0000 Subject: [PATCH 13/17] Backends: Metal: Remove weak ref (#5122, #5123) --- backends/imgui_impl_metal.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 358103f1..d2eb4651 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -583,7 +583,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects() indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx); } - __weak id weakSelf = self; + id weakSelf = self; [commandBuffer addCompletedHandler:^(id) { dispatch_async(dispatch_get_main_queue(), ^{ From c5f67218bff70ea6b885f7a52687acf9c414ba67 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 25 Feb 2022 17:18:40 +0100 Subject: [PATCH 14/17] Backends: SDL: Fix multi-viewport dragging issue with SDL on some systems. (v2 for master, using bd->MouseButtonsDown == 0) (#5012, #5082) # Conflicts: # backends/imgui_impl_sdl.cpp # docs/CHANGELOG.txt --- backends/imgui_impl_sdl.cpp | 24 ++++++++++++++++++++---- docs/CHANGELOG.txt | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index b314dbb9..bed000be 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -18,9 +18,10 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-03-22: Inputs: Fix mouse position issues when dragging outside of boundaries. SDL_CaptureMouse() erroneously still gives out LEAVE events when hovering OS decorations. // 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). // 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer. -// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. +// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates. @@ -85,6 +86,7 @@ struct ImGui_ImplSDL2_Data Uint64 Time; int MouseButtonsDown; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; + int PendingMouseLeaveFrame; char* ClipboardTextData; bool MouseCanUseGlobalState; @@ -292,9 +294,17 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_WINDOWEVENT: { - if (event->window.event == SDL_WINDOWEVENT_LEAVE) - io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); - if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED) + // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. + // - However we won't get a correct LEAVE event for a captured window. + // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why + // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. + Uint8 window_event = event->window.event; + if (window_event == SDL_WINDOWEVENT_ENTER) + bd->PendingMouseLeaveFrame = 0; + if (window_event == SDL_WINDOWEVENT_LEAVE) + bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; + if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST) io.AddFocusEvent(false); @@ -540,6 +550,12 @@ void ImGui_ImplSDL2_NewFrame() io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); bd->Time = current_time; + if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0) + { + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + bd->PendingMouseLeaveFrame = 0; + } + ImGui_ImplSDL2_UpdateMouseData(); ImGui_ImplSDL2_UpdateMouseCursor(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 54d22d7f..29b6bac7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,6 +69,7 @@ Other Changes: - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] +- Backends: SDL: Fixed dragging out viewport broken on some SDL setups. (#5012) [@rokups] - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Examples: Emscripten: Fix building for latest Emscripten specs. (#3632) From 3c07879504adec0d1b96c10c0f1578c009e070ae Mon Sep 17 00:00:00 2001 From: thedmd Date: Tue, 22 Mar 2022 18:45:27 +0100 Subject: [PATCH 15/17] Backends: OSX: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) --- backends/imgui_impl_osx.mm | 3 ++- docs/CHANGELOG.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index ec0a25b8..3c6635c1 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-03-22: Inputs: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key // 2022-02-07: Inputs: Forward keyDown/keyUp events to OS when unused by dear imgui. // 2022-01-31: Fix building with old Xcode versions that are missing gamepad features. // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. @@ -429,7 +430,7 @@ bool ImGui_ImplOSX_Init(NSView* view) // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down). // This monitor taps into global event stream and captures these events. - NSEventMask eventMask = NSEventMaskFlagsChanged; + NSEventMask eventMask = NSEventMaskFromType(NSKeyUp) | NSEventMaskFlagsChanged; [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event) { ImGui_ImplOSX_HandleEvent(event, g_KeyEventResponder); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 29b6bac7..c6228fbc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,7 @@ Other Changes: - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] - Backends: SDL: Fixed dragging out viewport broken on some SDL setups. (#5012) [@rokups] - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] +- Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd] - Examples: Emscripten: Fix building for latest Emscripten specs. (#3632) From 7d7bf993bb0c37c9eadb22de456ea6be021451f8 Mon Sep 17 00:00:00 2001 From: cfillion Date: Tue, 22 Mar 2022 20:24:38 -0400 Subject: [PATCH 16/17] ImDrawList: Fix texture-based anti-aliasing with RGBA textures (#5132, #3245) When using an Alpha8 font texture, GetTexDataAsRGBA32 converts 0x00 to transparent white. When using a RGBA32 font texture, ImFontAtlasBuildRenderLinesTexData was writing transparent black. --- docs/CHANGELOG.txt | 1 + imgui_draw.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c6228fbc..1b95abc0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other Changes: - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - Stack Tool: Added option to copy item path to clipboard. (#4631) - Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd] +- DrawList: Fixed texture-based anti-aliasing path with RGBA textures (#5132, #3245) [@cfillion] - Misc: Fixed IsAnyItemHovered() returning false when using navigation. - Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu] - Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e9197586..3fbe99bf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2738,13 +2738,13 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas) { unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)]; for (unsigned int i = 0; i < pad_left; i++) - *(write_ptr + i) = IM_COL32_BLACK_TRANS; + *(write_ptr + i) = IM_COL32(255, 255, 255, 0); for (unsigned int i = 0; i < line_width; i++) *(write_ptr + pad_left + i) = IM_COL32_WHITE; for (unsigned int i = 0; i < pad_right; i++) - *(write_ptr + pad_left + line_width + i) = IM_COL32_BLACK_TRANS; + *(write_ptr + pad_left + line_width + i) = IM_COL32(255, 255, 255, 0); } // Calculate UVs for this line From 1ad8ad623e7ec16f9ffb6b86ddf68bfd8deb43b9 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 23 Mar 2022 15:01:57 +0200 Subject: [PATCH 17/17] Backends: GLFW: Fixed keyboard modifiers events being reported incorrectly on Linux/X11. --- backends/imgui_impl_glfw.cpp | 19 ++++++++++++++++++- docs/CHANGELOG.txt | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 6cdf7494..5670f106 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,7 +16,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after iniitializing backend. +// 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11. +// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend. // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago)with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). @@ -244,6 +245,19 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) } } +static int ImGui_ImplGlfw_KeyToModifier(int key) +{ + if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL) + return GLFW_MOD_CONTROL; + if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT) + return GLFW_MOD_SHIFT; + if (key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT) + return GLFW_MOD_ALT; + if (key == GLFW_KEY_LEFT_SUPER || key == GLFW_KEY_RIGHT_SUPER) + return GLFW_MOD_SUPER; + return 0; +} + static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods) { ImGuiIO& io = ImGui::GetIO(); @@ -312,6 +326,9 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i if (action != GLFW_PRESS && action != GLFW_RELEASE) return; + // Workaround: X11 does not include current pressed/released modifier key in 'mods' flags. https://github.com/glfw/glfw/issues/1630 + if (int keycode_to_mod = ImGui_ImplGlfw_KeyToModifier(keycode)) + mods = (action == GLFW_PRESS) ? (mods | keycode_to_mod) : (mods & ~keycode_to_mod); ImGui_ImplGlfw_UpdateKeyModifiers(mods); keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1b95abc0..9fb774ff 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,8 @@ Other Changes: - Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075) - Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov] - ImVector: Fixed erase() with empty range. (#5009) [@thedmd] +- Backends: GLFW: Fixed a regression in 1.87 which resulted in keyboard modifiers events being + reported incorrectly on Linux/X11, due to a bug in GLFW. [@rokups] - Backends: SDL: Fixed dragging out viewport broken on some SDL setups. (#5012) [@rokups] - Backends: SDL: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2). (#5125) [@sgiurgiu] - Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd]