diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd1d0d47e..3980838a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -575,8 +575,8 @@ jobs: - name: Build macOS example_sdl2_metal run: make -C examples/example_sdl2_metal - - name: Build macOS example_sdl3_metal4 - run: make -C examples/example_sdl3_metal4 + #- name: Build macOS example_sdl3_metal4 + # run: make -C examples/example_sdl3_metal4 - name: Build macOS example_sdl2_opengl2 run: make -C examples/example_sdl2_opengl2 diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 0c12392a3..62afb25d4 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -131,7 +131,6 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, ImGui_ImplMetal_RenderDrawData(draw_data, (__bridge id)(commandBuffer), (__bridge id)(commandEncoder)); - } bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device) diff --git a/backends/imgui_impl_metal4.h b/backends/imgui_impl_metal4.h index 718897317..ac4c389fe 100644 --- a/backends/imgui_impl_metal4.h +++ b/backends/imgui_impl_metal4.h @@ -1,12 +1,12 @@ // dear imgui: Renderer Backend for Metal 4 // This needs to be used along with a Platform Backend (e.g. OSX) +// Metal 4 requires Apple Silicon and macOS 26+. // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture.gpuResourceID' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // Missing features or Issues: -// [ ] Metal-cpp support. // [ ] Texture view pool support? Reevaluate which type to use for ImtextureID. // [ ] Renderer: Multi-viewport support (multiple windows). @@ -53,6 +53,38 @@ IMGUI_IMPL_API void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex); #endif +//----------------------------------------------------------------------------- +// C++ API +//----------------------------------------------------------------------------- + +// Enable Metal C++ binding support with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file +// More info about using Metal from C++: https://developer.apple.com/metal/cpp/ + +#ifdef IMGUI_IMPL_METAL_CPP +#ifndef __OBJC__ + +// Forward declare relevant classes from the MTL and MTL4 namespace +namespace MTL { class Device; } +namespace MTL4 { class CommandQueue; class CommandBuffer; class RenderPassDescriptor; class RenderCommandEncoder; } + +// Follow "Getting Started" link and check examples/ folder to learn about using backends! +IMGUI_IMPL_API bool ImGui_ImplMetal4_Init(MTL::Device* device, MTL4::CommandQueue* commandQueue, int framesInFlight); +IMGUI_IMPL_API void ImGui_ImplMetal4_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplMetal4_NewFrame(MTL4::RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex); +IMGUI_IMPL_API void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, + MTL4::CommandBuffer* commandBuffer, + MTL4::RenderCommandEncoder* commandEncoder); + +// Called by Init/NewFrame/Shutdown +IMGUI_IMPL_API bool ImGui_ImplMetal4_CreateDeviceObjects(MTL::Device* device); +IMGUI_IMPL_API void ImGui_ImplMetal4_DestroyDeviceObjects(); + +// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually. +IMGUI_IMPL_API void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex); + +#endif +#endif + //----------------------------------------------------------------------------- #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_metal4.mm b/backends/imgui_impl_metal4.mm index b90828481..75116e36c 100644 --- a/backends/imgui_impl_metal4.mm +++ b/backends/imgui_impl_metal4.mm @@ -1,12 +1,12 @@ // dear imgui: Renderer Backend for Metal 4 // This needs to be used along with a Platform Backend (e.g. OSX) +// Metal 4 requires Apple Silicon and macOS 26+. // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // Missing features or Issues: -// [ ] Metal-cpp support. // [ ] Texture view pool support? Reevaluate which type to use for ImtextureID. // [ ] Renderer: Multi-viewport support (multiple windows). @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2026-07-07: Metal 4: Added metal-cpp support. (#9461) // 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458) #include "imgui.h" @@ -28,6 +29,10 @@ #import #import +#ifdef IMGUI_IMPL_METAL_CPP +#include +#endif + #pragma mark - Support classes and structs struct ImGui_Metal4_ConstantData @@ -95,6 +100,36 @@ static void ImGui_ImplMetal4_DestroyBackendData(){ IM_DELET static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); } +#ifdef IMGUI_IMPL_METAL_CPP + +#pragma mark - Dear ImGui Metal C++ Backend API + +bool ImGui_ImplMetal4_Init(MTL::Device* device, MTL4::CommandQueue* commandQueue, int framesInFlight) +{ + return ImGui_ImplMetal4_Init((__bridge id)(device),(__bridge id)(commandQueue), framesInFlight); +} + +void ImGui_ImplMetal4_NewFrame(MTL4::RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex) +{ + ImGui_ImplMetal4_NewFrame((__bridge MTL4RenderPassDescriptor*)(renderPassDescriptor), frameInFlightIndex); +} + +void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, + MTL4::CommandBuffer* commandBuffer, + MTL4::RenderCommandEncoder* commandEncoder) +{ + ImGui_ImplMetal4_RenderDrawData(draw_data, + (__bridge id)(commandBuffer), + (__bridge id)(commandEncoder)); +} + +bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device) +{ + return ImGui_ImplMetal4_CreateDeviceObjects((__bridge id)(device)); +} + +#endif // #ifdef IMGUI_IMPL_METAL_CPP + #pragma mark - Dear ImGui Metal Backend API void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex) @@ -205,9 +240,6 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, idDisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) - // Before rendering command lists, commit residency set - [bd->SharedMetalContext.residencySet commit]; - // Render command lists size_t vertexBufferOffset = 0; size_t indexBufferOffset = 0; @@ -258,6 +290,7 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id texture = (__bridge id)(void*)(intptr_t)tex_id; + [bd->SharedMetalContext.residencySet addAllocation:texture]; [bd->SharedMetalContext.argumentTable setTexture:texture.gpuResourceID atIndex:0]; } @@ -283,6 +316,9 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, idSharedMetalContext.residencySet commit]; bd->RenderCommandEncoder = nil; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 141f46275..8db85fb46 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking Changes: - TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`. +- ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in + of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover. + Other Changes: @@ -110,6 +113,12 @@ Other Changes: - Added io.MouseSingleClickDelay to configure default delayed single click delay when using GetItemClickedCountWithSingleClickDelay() or IsMouseReleasedWithDelay(). (#8337) Note that io.MouseSingleClickDelay is always > io.MouseDoubleClickTime. +- ColorEdit: + - Added `io.ConfigColorEditFlags` to read/modify current color edit/picker settings. + - ColorPicker: added `ImGuiColorEditFlags_PickerNoRotate` to disable rotation of the + S/V triangle when in `ImGuiColorEditFlags_PickerHueWheel` mode. (#9337) [@SeanTheBuilder1] + Likely best passed to `style.ColorEditFlags` to setup globally and once. + - ColorButton: small rendering tweak/optimization for the alpha checkerboard. - Style: - Added style.MenuItemRounding, ImGuiStyleVar_MenuItemRounding. (#7589, #9375, #9453) - Added style.SelectableRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453) @@ -131,8 +140,6 @@ Other Changes: - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) - Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText() coordinates for a given scope. (#3437, #9417, #2291) -- ColorButton: - - Small rendering tweak/optimization for the alpha checkerboard. - Demo: - Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced' demo for clarity (manual reimplementation of basic selection). @@ -141,7 +148,7 @@ Other Changes: - Backends: - Metal4: - Added new Metal 4 backend (forked from Metal 3 backend). (#9458, #9451) [@AmelieHeinrich] - Note that Metal-cpp is not yet supported. + - Added Metal-cpp support enabled with `IMGUI_IMPL_METAL_CPP` define. (#9461) [@MERL10N] - OpenGL3: - GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS] @@ -151,8 +158,12 @@ Other Changes: - Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()` when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends to spawn multiple-thread to manage OpenGL. (#9403) -- Examples: +- Examples: - Android: update to AGP 9.2.0 to support Gradle 9.6.0. + - OpenGL3+GLFW/SDL2/SDL3: allow Wine compatibility by passing empty GLSL version + string to ImGui_ImplOpenGL3_Init() to let backend decide of a GLSL version based + on actual GL version obtained. (#9427, #6577) [@perminovVS] + - OpenGL3+Win32: rework context creation to allow Wine compatibility. (#9427, #6577) [@perminovVS] - SDL2/SDL3: use `SDL_GetWindowSizeInPixels()` to create frame-buffers. Fixes issues with non-fractional framebuffer size on Wayland. (#8761, #9124) [@billtran1632001] - SDL3+Metal4: added new example. (#9458, #9451) [@AmelieHeinrich] diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index e487fe732..97c7532cc 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -41,29 +41,26 @@ int main(int, char**) if (!glfwInit()) return 1; - // Decide GL+GLSL versions + // Select GL version + let the backend select a GLSL version + const char* glsl_version = nullptr; #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 (WebGL 1.0) - const char* glsl_version = "#version 100"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); #elif defined(IMGUI_IMPL_OPENGL_ES3) // GL ES 3.0 + GLSL 300 es (WebGL 2.0) - const char* glsl_version = "#version 300 es"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); #elif defined(__APPLE__) - // GL 3.2 + GLSL 150 - const char* glsl_version = "#version 150"; + // GL 3.2 + generally GLSL 150 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac #else - // GL 3.0 + GLSL 130 - const char* glsl_version = "#version 130"; + // GL 3.0 + generally GLSL 130 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index 1c51e59d9..f7c934f0d 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -39,31 +39,28 @@ int main(int, char**) return 1; } - // Decide GL+GLSL versions + // Select GL version + let the backend select a GLSL version + const char* glsl_version = nullptr; #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 (WebGL 1.0) - const char* glsl_version = "#version 100"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #elif defined(IMGUI_IMPL_OPENGL_ES3) // GL ES 3.0 + GLSL 300 es (WebGL 2.0) - const char* glsl_version = "#version 300 es"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #elif defined(__APPLE__) - // GL 3.2 Core + GLSL 150 - const char* glsl_version = "#version 150"; + // GL 3.2 Core + generally GLSL 150 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); #else - // GL 3.0 + GLSL 130 - const char* glsl_version = "#version 130"; + // GL 3.0 + generally GLSL 130 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); diff --git a/examples/example_sdl3_metal4/main.mm b/examples/example_sdl3_metal4/main.mm index d80b4dde0..6debb5133 100644 --- a/examples/example_sdl3_metal4/main.mm +++ b/examples/example_sdl3_metal4/main.mm @@ -1,5 +1,6 @@ // Dear ImGui: standalone example application for SDL3 + Metal 4 // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) +// (Metal 4 requires Apple Silicon and macOS 26+.) // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 07f0cd025..6900f34d7 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -33,31 +33,28 @@ int main(int, char**) return 1; } - // Decide GL+GLSL versions + // Select GL version + let the backend select a GLSL version + const char* glsl_version = nullptr; #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 (WebGL 1.0) - const char* glsl_version = "#version 100"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #elif defined(IMGUI_IMPL_OPENGL_ES3) // GL ES 3.0 + GLSL 300 es (WebGL 2.0) - const char* glsl_version = "#version 300 es"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #elif defined(__APPLE__) - // GL 3.2 Core + GLSL 150 - const char* glsl_version = "#version 150"; + // GL 3.2 Core + generally GLSL 150 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); #else - // GL 3.0 + GLSL 130 - const char* glsl_version = "#version 130"; + // GL 3.0 + generally GLSL 130 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); diff --git a/examples/example_win32_opengl3/main.cpp b/examples/example_win32_opengl3/main.cpp index ee77ee21b..7652fa84d 100644 --- a/examples/example_win32_opengl3/main.cpp +++ b/examples/example_win32_opengl3/main.cpp @@ -17,12 +17,13 @@ #include #include #include +#include // Data stored per platform window struct WGL_WindowData { HDC hDC; }; // Data -static HGLRC g_hRC; +static HGLRC g_hRC; // Rendering context static WGL_WindowData g_MainWindow; static int g_Width; static int g_Height; @@ -279,8 +280,57 @@ bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data) ::ReleaseDC(hWnd, hDc); data->hDC = ::GetDC(hWnd); - if (!g_hRC) - g_hRC = wglCreateContext(data->hDC); + if (g_hRC) + return true; + + // Create legacy context + HGLRC tempRC = wglCreateContext(data->hDC); + if (!tempRC) { ::ReleaseDC(hWnd, data->hDC); return false; } + if (!wglMakeCurrent(data->hDC, tempRC)) + { + wglDeleteContext(tempRC); + ::ReleaseDC(hWnd, data->hDC); + return false; + } + + // Get context version + GLint major = 0, minor = 0; + glGetIntegerv(0x821B, &major); // GL_MAJOR_VERSION + glGetIntegerv(0x821C, &minor); // GL_MINOR_VERSION + const char* gl_version_str = (const char*)glGetString(GL_VERSION); + if (major == 0 && minor == 0) + sscanf_s(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "." + const GLuint gl_version = (GLuint)(major * 100 + minor * 10); + + // Keep temporary context: already OpenGL 3.0+. + g_hRC = tempRC; + if (gl_version >= 300) + return true; + + typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*); + const PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + + // GL 3.0 + const int attribs[] = + { + 0x2091, 3, // WGL_CONTEXT_MAJOR_VERSION_ARB + 0x2092, 0, // WGL_CONTEXT_MINOR_VERSION_ARB + 0x9126, 0x0001, // WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB + 0 + }; + HGLRC newRC = nullptr; + if (wglCreateContextAttribsARB) + newRC = wglCreateContextAttribsARB(data->hDC, 0, attribs); + + // If we managed to create 3.0+ context: use that one and destroy the temporary OpenGL 2.x compatibility context. + if (newRC) + { + wglMakeCurrent(nullptr, nullptr); + wglDeleteContext(tempRC); + g_hRC = newRC; + wglMakeCurrent(data->hDC, g_hRC); + } + return true; } diff --git a/imgui.cpp b/imgui.cpp index a06535c6a..6ff4bfa2b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -402,6 +402,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos) - likewise io.MousePos and GetMousePos() will use OS coordinates. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. + - 2026/07/06 (1.92.9) - ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover. - 2026/06/02 (1.92.9) - TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead. - 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke(). - Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); @@ -1714,8 +1715,7 @@ ImGuiIO::ImGuiIO() ConfigViewportsNoDefaultParent = true; ConfigViewportsPlatformFocusSetsImGuiFocus = true; - // Miscellaneous options - MouseDrawCursor = false; + // Widget options #ifdef __APPLE__ ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag #else @@ -1725,13 +1725,21 @@ ImGuiIO::ImGuiIO() ConfigInputTextCursorBlink = true; ConfigInputTextEnterKeepActive = false; ConfigDragClickToInputText = false; + ConfigColorEditFlags = ImGuiColorEditFlags_DefaultOptions_; // Current settings for ColorEdit/ColorPicker widgets. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions. ConfigWindowsResizeFromEdges = true; ConfigWindowsMoveFromTitleBarOnly = false; ConfigWindowsCopyContentsWithCtrlC = false; ConfigScrollbarScrollByPage = true; + + // Ini Settings options ConfigIniSettingsSaveLastUsedDate = true; ConfigIniSettingsAutoDiscardMonths = 0; + ConfigDebugIniSettings = false; + + // Miscellaneous options + MouseDrawCursor = false; ConfigMemoryCompactTimer = 60.0f; + ConfigDebugIsDebuggerPresent = false; ConfigDebugHighlightIdConflicts = true; ConfigDebugHighlightIdConflictsShowItemPicker = true; @@ -4440,7 +4448,6 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) TempInputId = 0; memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue)); BeginMenuDepth = BeginComboDepth = 0; - ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditCurrentID = ColorEditSavedID = 0; ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedColor = 0; @@ -11703,6 +11710,11 @@ static void ImGui::ErrorCheckNewFrameSanityChecks() IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders. IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right); + IM_ASSERT(ImIsPowerOfTwo(g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected + IM_ASSERT(ImIsPowerOfTwo(g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DataTypeMask_)); // " + IM_ASSERT(ImIsPowerOfTwo(g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_PickerMask_)); // " + IM_ASSERT(ImIsPowerOfTwo(g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_InputMask_)); // " + IM_ASSERT(g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesNone || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesFull || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesToNodes); IM_ASSERT(g.IO.MouseSingleClickDelay > g.IO.MouseDoubleClickTime); @@ -16422,14 +16434,21 @@ void ImGui::ClearIniSettings() void ImGui::CleanupIniSettings(ImGuiSettingsCleanupArgs* args) { ImGuiContext& g = *GImGui; - if (g.PlatformIO.Platform_SessionDate == 0) - return; - ImGuiPackedDate discard_older_than_date_p = g.PlatformIO.Platform_SessionDate; - discard_older_than_date_p.SubtractMonths(args->DiscardOlderThanMonths); - args->_DiscardOlderThanDate = discard_older_than_date_p.Unpack(); + if (args->DiscardAll) + for (ImGuiSettingsHandler& handler : g.SettingsHandlers) + if (args->TypeHashFilter == 0 || handler.TypeHash == args->TypeHashFilter) + if (handler.ClearAllFn != NULL) + handler.ClearAllFn(&g, &handler); + if (g.PlatformIO.Platform_SessionDate != 0 && args->DiscardOlderThanMonths != 0) + { + ImGuiPackedDate discard_older_than_date_p = g.PlatformIO.Platform_SessionDate; + discard_older_than_date_p.SubtractMonths(args->DiscardOlderThanMonths); + args->_DiscardOlderThanDate = discard_older_than_date_p.Unpack(); + } for (ImGuiSettingsHandler& handler : g.SettingsHandlers) - if (handler.CleanupFn != NULL) - handler.CleanupFn(&g, &handler, args); + if (args->TypeHashFilter == 0 || handler.TypeHash == args->TypeHashFilter) + if (handler.CleanupFn != NULL) + handler.CleanupFn(&g, &handler, args); } void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) @@ -16617,9 +16636,10 @@ static void WindowSettingsHandler_Cleanup(ImGuiContext* ctx, ImGuiSettingsHandle ImGuiContext& g = *ctx; for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) { - if (args->_DiscardOlderThanDate != 0 && settings->LastUsedDate.Unpack() < args->_DiscardOlderThanDate) + const bool is_valid = settings->LastUsedDate.IsValid(); + if ((args->_DiscardOlderThanDate != 0 && settings->LastUsedDate.Unpack() < args->_DiscardOlderThanDate) || (args->DiscardWhenMissingDate && !is_valid)) settings->WantDelete = true; - if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && settings->LastUsedDate.IsValid() == false)) + if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && !is_valid)) settings->LastUsedDate = g.SessionDate; } } diff --git a/imgui.h b/imgui.h index c79fc3732..3920f72c2 100644 --- a/imgui.h +++ b/imgui.h @@ -30,7 +30,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.9 WIP" -#define IMGUI_VERSION_NUM 19284 +#define IMGUI_VERSION_NUM 19285 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 #define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. @@ -247,7 +247,7 @@ typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: f typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton() typedef int ImGuiChildFlags; // -> enum ImGuiChildFlags_ // Flags: for BeginChild() -typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc. +typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4(), io.ConfigColorEditFlags etc. typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo() typedef int ImGuiDockNodeFlags; // -> enum ImGuiDockNodeFlags_ // Flags: for DockSpace() @@ -745,7 +745,6 @@ namespace ImGui IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. - IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. // Widgets: Trees // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. @@ -1991,7 +1990,8 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_AlphaNoBg = 1 << 13, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color. ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 14, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview. - // User Options (right-click on widget to change some of them). + // User Options (right-click on widget to change some of them) + // Current settings are stored in style.ColorEditFlags. ImGuiColorEditFlags_AlphaBar = 1 << 18, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex. @@ -2001,11 +2001,13 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers. ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [Picker] // ColorPicker: bar for Hue, rectangle for Sat/Value. ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [Picker] // ColorPicker: wheel for Hue, triangle for Sat/Value. - ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format. - ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format. + ImGuiColorEditFlags_PickerNoRotate = 1 << 27, // [Picker] // ColorPicker: disable rotating Sat/Value triangle. Best set in io.ConfigColorEditFlags once. + ImGuiColorEditFlags_InputRGB = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format. + ImGuiColorEditFlags_InputHSV = 1 << 29, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format. - // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to - // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup. + // Defaults Options copied to io.ConfigColorEditFlags during initialization. + // The intent is that you probably don't want to override them in most of your calls. + // Let the user choose via the option menu and/or modify io.ConfigColorEditFlags directly during startup if you want. ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, // [Internal] Masks @@ -2018,8 +2020,8 @@ enum ImGuiColorEditFlags_ // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiColorEditFlags_AlphaPreview = 0, // Removed in 1.91.8. This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set. -#endif //ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69] +#endif }; // Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. @@ -2544,7 +2546,19 @@ struct ImGuiIO bool ConfigDpiScaleFonts; // = false // [EXPERIMENTAL] Automatically overwrite style.FontScaleDpi when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now. bool ConfigDpiScaleViewports; // = false // [EXPERIMENTAL] Scale Dear ImGui and Platform Windows when Monitor DPI changes. - // Ini Settings + // Widget options + bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. + bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. + bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). + bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only). + ImGuiColorEditFlags ConfigColorEditFlags; // = // Current settings for ColorEdit/ColorPicker widgets. Must have one bit of ImGuiColorEditFlags_DisplayMask_, one bit of ImGuiColorEditFlags_DataTypeMask_, one bit of ImGuiColorEditFlags_PickerMask_, one bit of ImGuiColorEditFlags_InputMask_. Defaults to ImGuiColorEditFlags_DefaultOptions_. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions. + bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. + bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) + bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. + bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order. + bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location. + + // Ini Settings options bool ConfigIniSettingsSaveLastUsedDate;// = true // Enable loading/saving last used day (YYYYMMDD) in some .ini struct, making things easier to audit and allowing custom tools to cleanup old data. int ConfigIniSettingsAutoDiscardMonths; // = 0 // [BETA] Set number of months after which unused .ini entries are discarded on load. Require platform_io.Platform_SessionDate to be set. For systems supporting the feature, .ini entries without a LastUsed field will always be discarded! Please report if you are using this. bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower) @@ -2552,15 +2566,6 @@ struct ImGuiIO // Miscellaneous options // (you can visualize and interact with all options in 'Demo->Configuration') bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. - bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. - bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. - bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). - bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only). - bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. - bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) - bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. - bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order. - bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location. float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. // Inputs Behaviors @@ -4374,6 +4379,8 @@ struct ImGuiPlatformImeData #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.92.9 (from July 2026) + IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // set current options for if you want to select a default format, picker type, etc. User will be able to change those settings, unless you pass the _NoOptions flag to your calls. // OBSOLETED in 1.92.0 (from June 2025) inline void PushFont(ImFont* font) { PushFont(font, font ? font->LegacySize : 0.0f); } IMGUI_API void SetWindowFontScale(float scale); // Set font scale factor for current window. Prefer using PushFont(NULL, style.FontSizeBase * factor) or use style.FontScaleMain to scale all windows. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8e6dd9b32..550f3f098 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1397,6 +1397,7 @@ static void DemoWindowWidgetsColorAndPickers() ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | base_flags); } } + ImGui::CheckboxFlags("ImGuiColorEditFlags_PickerNoRotate", &color_picker_flags, ImGuiColorEditFlags_PickerNoRotate); ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0ImGuiColorEditFlags_PickerHueBar\0ImGuiColorEditFlags_PickerHueWheel\0"); ImGui::SameLine(); HelpMarker("When not specified explicitly, user can right-click the picker to change mode."); @@ -1405,7 +1406,7 @@ static void DemoWindowWidgetsColorAndPickers() ImGui::SameLine(); HelpMarker( "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex " - "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); + "if you don't specify a display mode.\n\nYou can change the defaults using io.ConfigColorEditFlags."); ImGuiColorEditFlags flags = base_flags | color_picker_flags; if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; @@ -1418,14 +1419,14 @@ static void DemoWindowWidgetsColorAndPickers() ImGui::Text("Set defaults in code:"); ImGui::SameLine(); HelpMarker( - "SetColorEditOptions() is designed to allow you to set boot-time default.\n" + "io.ConfigColorEditFlags is designed to allow you to set boot-time default.\n" "We don't have Push/Pop functions because you can force options on a per-widget basis if needed, " "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid " "encouraging you to persistently save values that aren't forward-compatible."); - if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar); - if (ImGui::Button("Default: Float + HDR + Hue Wheel")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); + if (ImGui::Button("Overwrite default: Uint8 + HSV + Hue Bar")) + ImGui::GetIO().ConfigColorEditFlags = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar; + if (ImGui::Button("Overwrite default: Float + HDR + Hue Wheel")) + ImGui::GetIO().ConfigColorEditFlags = ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel; // Always display a small version of both types of pickers // (that's in order to make it more visible in the demo to people who are skimming quickly through it) @@ -5177,7 +5178,8 @@ static void DemoWindowLayout() // If you want to create your own time line for a real application you may be better off manipulating // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets // yourself. You may also want to use the lower-level ImDrawList API. - int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); + const int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3); + const float base_w = ImGui::GetFontSize() * 3; for (int n = 0; n < num_buttons; n++) { if (n > 0) ImGui::SameLine(); @@ -5189,7 +5191,7 @@ static void DemoWindowLayout() ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f)); - ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f)); + ImGui::Button(label, ImVec2(base_w + sinf((float)(line + n)) * base_w * 0.5f, 0.0f)); ImGui::PopStyleColor(3); ImGui::PopID(); } diff --git a/imgui_internal.h b/imgui_internal.h index 316935dc7..d5d3fa55e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2238,7 +2238,10 @@ struct ImGuiWindowSettings struct ImGuiSettingsCleanupArgs { - int DiscardOlderThanMonths = 0; // Enable to discard entries older than XX months. + ImGuiID TypeHashFilter = 0; // Set to restrict cleanup to a given .ini type, e.g. == ImHashStr("Window"), ImHashStr("Table"). Otherwise every types supporting Cleanup will be affected. + int DiscardOlderThanMonths = 0; // Enable to discard entries older than XX months. + bool DiscardWhenMissingDate = false; // Enable to discard entries missing a date. + bool DiscardAll = false; // Enable to discard all entries = same as calling ClearIniSettings() except it may be filtered. bool SetCurrentSessionDateToAll = false; // Enable to write current SessionDate to all supporting entries. // Let us know in #9460 if you use this. bool SetCurrentSessionDateWhenMissingDate = false; // Enable to write current SessionDate to all supporting entries missing a date. // Let us know in #9460 if you use this. int _DiscardOlderThanDate = 0; // [Internal] @@ -2734,7 +2737,6 @@ struct ImGuiContext ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types int BeginMenuDepth; int BeginComboDepth; - ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others). ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips diff --git a/imgui_tables.cpp b/imgui_tables.cpp index aa0b89efe..e1328fe59 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3875,8 +3875,15 @@ static size_t TableSettingsCalcChunkSize(int columns_count) ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count) { ImGuiContext& g = *GImGui; - //ImGuiTableSettings* old_settings = TableSettingsFindByID(id); // Comment out sanity check to avoid unnecessary lookups. - //IM_ASSERT(old_settings == NULL || old_settings->ColumnsCountMax < columns_count); + if (ImGuiTableSettings* settings = TableSettingsFindByID(id)) + { + if (settings->ColumnsCountMax >= columns_count) + { + TableSettingsInit(settings, id, columns_count, settings->ColumnsCountMax); // Recycle + return settings; + } + settings->ID = 0; // Invalidate storage, we won't fit because of a count change + } ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count)); TableSettingsInit(settings, id, columns_count, columns_count); return settings; @@ -4134,9 +4141,12 @@ static void TableSettingsHandler_Cleanup(ImGuiContext* ctx, ImGuiSettingsHandler table->SettingsOffset = -1; for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) { + const bool is_valid = settings->LastUsedDate.IsValid(); if (args->_DiscardOlderThanDate != 0 && settings->LastUsedDate.Unpack() < args->_DiscardOlderThanDate) settings->ID = 0; - if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && settings->LastUsedDate.IsValid() == false)) + else if (args->DiscardWhenMissingDate && !is_valid) + settings->ID = 0; + else if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && !is_valid)) settings->LastUsedDate = g.SessionDate; } } @@ -4159,16 +4169,6 @@ static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, int columns_count = 0; if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2) return NULL; - - if (ImGuiTableSettings* settings = ImGui::TableSettingsFindByID(id)) - { - if (settings->ColumnsCountMax >= columns_count) - { - TableSettingsInit(settings, id, columns_count, settings->ColumnsCountMax); // Recycle - return settings; - } - settings->ID = 0; // Invalidate storage, we won't fit because of a count change - } return ImGui::TableSettingsCreate(id, columns_count); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9fef56555..7fafa67d5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5758,7 +5758,6 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) // - RenderColorRectWithAlphaCheckerboard() [Internal] // - ColorPicker4() // - ColorButton() -// - SetColorEditOptions() // - ColorTooltip() [Internal] // - ColorEditOptionsPopup() [Internal] // - ColorPickerOptionsPopup() [Internal] @@ -5830,14 +5829,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag // Read stored options if (!(flags & ImGuiColorEditFlags_DisplayMask_)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_); + flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DisplayMask_); if (!(flags & ImGuiColorEditFlags_DataTypeMask_)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_); + flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DataTypeMask_); if (!(flags & ImGuiColorEditFlags_PickerMask_)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_); + flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_PickerMask_); if (!(flags & ImGuiColorEditFlags_InputMask_)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_); - flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_)); + flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_InputMask_); + flags |= (g.IO.ConfigColorEditFlags & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_)); IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected @@ -6106,13 +6105,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl // Read stored options if (!(flags & ImGuiColorEditFlags_PickerMask_)) - flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_; + flags |= ((g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_PickerMask_) ? g.IO.ConfigColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_; if (!(flags & ImGuiColorEditFlags_InputMask_)) - flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_; + flags |= ((g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_InputMask_) ? g.IO.ConfigColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected if (!(flags & ImGuiColorEditFlags_NoOptions)) - flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); + flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_AlphaBar); // Setup int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; @@ -6134,10 +6133,11 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f); // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic. + const bool triangle_rotate = (flags & ImGuiColorEditFlags_PickerNoRotate) == 0; float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f); - ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point. - ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point. - ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point. + ImVec2 triangle_pa = triangle_rotate ? ImVec2(triangle_r, 0.0f) : ImVec2(triangle_r * +0.866f, triangle_r * +0.5f); // Hue point. + ImVec2 triangle_pb = triangle_rotate ? ImVec2(triangle_r * -0.5f, triangle_r * -0.866f) : ImVec2(0.0f, -triangle_r); // Black point. + ImVec2 triangle_pc = triangle_rotate ? ImVec2(triangle_r * -0.5f, triangle_r * +0.866f) : ImVec2(triangle_r * -0.866f, triangle_r * +0.5f); // White point. float H = col[0], S = col[1], V = col[2]; float R = col[0], G = col[1], B = col[2]; @@ -6172,8 +6172,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl H += 1.0f; value_changed = value_changed_h = true; } - float cos_hue_angle = ImCos(-H * 2.0f * IM_PI); - float sin_hue_angle = ImSin(-H * 2.0f * IM_PI); + float cos_hue_angle = triangle_rotate ? ImCos(-H * 2.0f * IM_PI) : 1.0f; + float sin_hue_angle = triangle_rotate ? ImSin(-H * 2.0f * IM_PI) : 0.0f; if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle))) { // Interacting with SV triangle @@ -6382,6 +6382,11 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); + if (triangle_rotate == false) + { + cos_hue_angle = 1.0f; + sin_hue_angle = 0.0f; + } // Render SV triangle (rotated according to hue) ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); @@ -6532,25 +6537,18 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl return pressed; } -// Initialize/override default color options -// FIXME: Could be moved to a simple IO field. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +// This allowed passing 0 to set default, whereas NewFrame() will assert if one of missing. Abide to old logic. void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) { ImGuiContext& g = *GImGui; - if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0) - flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_; - if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0) - flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_; - if ((flags & ImGuiColorEditFlags_PickerMask_) == 0) - flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_; - if ((flags & ImGuiColorEditFlags_InputMask_) == 0) - flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_; - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected - IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected - g.ColorEditOptions = flags; + if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_; } + if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_; } + if ((flags & ImGuiColorEditFlags_PickerMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_; } + if ((flags & ImGuiColorEditFlags_InputMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_; } + g.IO.ConfigColorEditFlags = flags; } +#endif // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags) @@ -6598,7 +6596,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) ImGuiContext& g = *GImGui; PushItemFlag(ImGuiItemFlags_NoMarkEdited, true); - ImGuiColorEditFlags opts = g.ColorEditOptions; + ImGuiColorEditFlags opts = g.IO.ConfigColorEditFlags; if (allow_opt_inputs) { if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB; @@ -6638,7 +6636,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) EndPopup(); } - g.ColorEditOptions = opts; + g.IO.ConfigColorEditFlags = opts; PopItemFlag(); EndPopup(); } @@ -6666,7 +6664,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel; ImVec2 backup_pos = GetCursorScreenPos(); if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup - g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_); + g.IO.ConfigColorEditFlags = (g.IO.ConfigColorEditFlags & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_); SetCursorScreenPos(backup_pos); ImVec4 previewing_ref_col; memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4)); @@ -6678,7 +6676,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl if (allow_opt_alpha_bar) { if (allow_opt_picker) Separator(); - CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar); + CheckboxFlags("Alpha Bar", &g.IO.ConfigColorEditFlags, ImGuiColorEditFlags_AlphaBar); } PopItemFlag(); EndPopup();