diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ee729717..482804b47 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -343,7 +343,7 @@ jobs: EOF g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp - - name: Build example_null (with large ImDrawIdx + pointer ImTextureID) + - name: Build example_null (with large ImDrawIdx + custom ImTextureID) run: | cat > example_single_file.cpp <<'EOF' @@ -356,6 +356,21 @@ jobs: EOF g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp + cat > example_single_file.cpp <<'EOF' + + // Test build ImTextureID defined as a struct + struct SomeType { int a = 0; int b = 0; }; + #define ImTextureID SomeType + #define ImTextureID_Invalid SomeType() + inline bool operator==(const SomeType& lhs, const SomeType& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } + inline bool operator!=(const SomeType& lhs, const SomeType& rhs) { return lhs.a != rhs.a || lhs.b != rhs.b; } + #define IMGUI_IMPLEMENTATION + #include "misc/single_file/imgui_single_file.h" + #include "examples/example_null/main.cpp" + + EOF + g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS) run: | cat > example_single_file.cpp <<'EOF' diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0ea344b65..f80cde344 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-11-24: Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784) // 2025-11-13: [Docking] Handle viewport surface creation failure without crashing. (#9068) // 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008) // 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo. @@ -1686,7 +1687,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; - info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) + info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + else if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) + info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + else + IM_ASSERT(false && "No supported composite alpha mode found!"); info.presentMode = wd->PresentMode; info.clipped = VK_TRUE; info.oldSwapchain = old_swapchain; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fecb21d7f..dfa0a9280 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,30 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.92.6 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking Changes: + +Other Changes: + +- Fonts: fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which + did erroneously make a copy of the font data, essentially defeating the purpose + of this flag and wasting memory. + Undetected since July 2015 and now spotted by @TellowKrinkle, this is perhaps + the oldest bug in Dear ImGui history (albeit for a rarely used feature)! (#9086) +- Textures: + - Fixed a building issue when ImTextureID is defined as a struct. + - Fixed displaying texture # in Metrics/Debugger window. +- Scrollbar: fixed a codepath leading to a divide-by-zero (which would not be + noticeable by user but detected by sanitizers). (#9089) [@judicaelclair] +- Backends: + - Vulkan: helper for creating a swapchain (used by examples and multi-viewports) + selects `VkSwapchainCreateInfoKHR`'s `compositeAlpha` value based on + `cap.supportedCompositeAlpha`. (#8784) [@FelixStach] + + ----------------------------------------------------------------------- VERSION 1.92.5 (Released 2025-11-20) ----------------------------------------------------------------------- @@ -1544,6 +1568,7 @@ Breaking changes: - Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before). - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). Use IsKeyDown() instead. - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022). + - GetKeyIndex() is removed (obsoleted March 2022). The indirection is now unnecessary. - Pre-1.87 backends are not supported: - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields. - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields. diff --git a/imgui.cpp b/imgui.cpp index 77c88c684..865513128 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (main code and documentation) // Help: @@ -536,6 +536,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: - 2024/11/06 (1.91.5) - commented/obsoleted out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before) - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022). + - GetKeyIndex() is removed (obsoleted March 2022). The indirection is now unnecessary. - pre-1.87 backends are not supported: - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields. - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields. @@ -21867,23 +21868,21 @@ void ImGui::UpdateDebugToolFlashStyleColor() DebugFlashStyleColorStop(); } -static const char* FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) +ImU64 ImGui::DebugTextureIDToU64(ImTextureID tex_id) { - union { void* ptr; int integer; } tex_id_opaque; - memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id))); - if (sizeof(tex_id) >= sizeof(void*)) - ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr); - else - ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer); - return buf; + ImU64 v = 0; + memcpy(&v, &tex_id, ImMin(sizeof(ImU64), sizeof(ImTextureID))); + return v; } static const char* FormatTextureRefForDebugDisplay(char* buf, int buf_size, ImTextureRef tex_ref) { + char* buf_p = buf; char* buf_end = buf + buf_size; if (tex_ref._TexData != NULL) - buf += ImFormatString(buf, buf_end - buf, "#%03d: ", tex_ref._TexData->UniqueID); - return FormatTextureIDForDebugDisplay(buf, (int)(buf_end - buf), tex_ref.GetTexID()); // Calling TexRef::GetTexID() to avoid assert of cmd->GetTexID() + buf_p += ImFormatString(buf_p, buf_end - buf_p, "#%03d: ", tex_ref._TexData->UniqueID); + ImFormatString(buf_p, buf_end - buf_p, "0x%X", ImGui::DebugTextureIDToU64(tex_ref.GetTexID())); + return buf; } #ifdef IMGUI_ENABLE_FREETYPE @@ -22069,9 +22068,9 @@ void ImGui::DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRe } PopStyleVar(); - char texid_desc[30]; + char texref_desc[30]; Text("Status = %s (%d), Format = %s (%d), UseColors = %d", ImTextureDataGetStatusName(tex->Status), tex->Status, ImTextureDataGetFormatName(tex->Format), tex->Format, tex->UseColors); - Text("TexID = %s, BackendUserData = %p", FormatTextureRefForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), tex->GetTexRef()), tex->BackendUserData); + Text("TexRef = %s, BackendUserData = %p", FormatTextureRefForDebugDisplay(texref_desc, IM_ARRAYSIZE(texref_desc), tex->GetTexRef()), tex->BackendUserData); TreePop(); } PopID(); diff --git a/imgui.h b/imgui.h index e42d702fb..50868e23a 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (headers) // Help: @@ -29,8 +29,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.92.5" -#define IMGUI_VERSION_NUM 19250 +#define IMGUI_VERSION "1.92.6 WIP" +#define IMGUI_VERSION_NUM 19251 #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. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d70fc7624..64f952d13 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 402727ab7..74aa3f91a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (drawing and font code) /* @@ -3058,12 +3058,6 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in) font->Sources.push_back(font_cfg); ImFontAtlasBuildUpdatePointers(this); // Pointers to Sources are otherwise dangling after we called Sources.push_back(). - if (font_cfg->FontDataOwnedByAtlas == false) - { - font_cfg->FontDataOwnedByAtlas = true; - font_cfg->FontData = ImMemdup(font_cfg->FontData, (size_t)font_cfg->FontDataSize); - } - // Sanity check // We don't round cfg.SizePixels yet as relative size of merged fonts are used afterwards. if (font_cfg->GlyphExcludeRanges != NULL) @@ -4550,16 +4544,16 @@ void ImFontAtlasDebugLogTextureRequests(ImFontAtlas* atlas) if (tex->Status == ImTextureStatus_WantCreate) IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: create %dx%d\n", tex->UniqueID, tex->Width, tex->Height); else if (tex->Status == ImTextureStatus_WantDestroy) - IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: destroy %dx%d, texid=0x%" IM_PRIX64 ", backend_data=%p\n", tex->UniqueID, tex->Width, tex->Height, IM_TEXTUREID_TO_U64(tex->TexID), tex->BackendUserData); + IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: destroy %dx%d, texid=0x%" IM_PRIX64 ", backend_data=%p\n", tex->UniqueID, tex->Width, tex->Height, ImGui::DebugTextureIDToU64(tex->TexID), tex->BackendUserData); else if (tex->Status == ImTextureStatus_WantUpdates) { - IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: update %d regions, texid=0x%" IM_PRIX64 ", backend_data=0x%" IM_PRIX64 "\n", tex->UniqueID, tex->Updates.Size, IM_TEXTUREID_TO_U64(tex->TexID), (ImU64)(intptr_t)tex->BackendUserData); + IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: update %d regions, texid=0x%" IM_PRIX64 ", backend_data=0x%" IM_PRIX64 "\n", tex->UniqueID, tex->Updates.Size, ImGui::DebugTextureIDToU64(tex->TexID), (ImU64)(intptr_t)tex->BackendUserData); for (const ImTextureRect& r : tex->Updates) { IM_UNUSED(r); IM_ASSERT(r.x >= 0 && r.y >= 0); IM_ASSERT(r.x + r.w <= tex->Width && r.y + r.h <= tex->Height); // In theory should subtract PackPadding but it's currently part of atlas and mid-frame change would wreck assert. - //IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: update (% 4d..%-4d)->(% 4d..%-4d), texid=0x%" IM_PRIX64 ", backend_data=0x%" IM_PRIX64 "\n", tex->UniqueID, r.x, r.y, r.x + r.w, r.y + r.h, IM_TEXTUREID_TO_U64(tex->TexID), (ImU64)(intptr_t)tex->BackendUserData); + //IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: update (% 4d..%-4d)->(% 4d..%-4d), texid=0x%" IM_PRIX64 ", backend_data=0x%" IM_PRIX64 "\n", tex->UniqueID, r.x, r.y, r.x + r.w, r.y + r.h, ImGui::DebugTextureIDToU64(tex->TexID), (ImU64)(intptr_t)tex->BackendUserData); } } } @@ -4589,14 +4583,14 @@ static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* IM_ASSERT(src->FontLoaderData == NULL); // Initialize helper structure for font loading and verify that the TTF/OTF data is correct - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)src->FontData, src->FontNo); + const int font_offset = stbtt_GetFontOffsetForIndex((const unsigned char*)src->FontData, src->FontNo); if (font_offset < 0) { IM_DELETE(bd_font_data); IM_ASSERT_USER_ERROR(0, "stbtt_GetFontOffsetForIndex(): FontData is incorrect, or FontNo cannot be found."); return false; } - if (!stbtt_InitFont(&bd_font_data->FontInfo, (unsigned char*)src->FontData, font_offset)) + if (!stbtt_InitFont(&bd_font_data->FontInfo, (const unsigned char*)src->FontData, font_offset)) { IM_DELETE(bd_font_data); IM_ASSERT_USER_ERROR(0, "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize."); diff --git a/imgui_internal.h b/imgui_internal.h index 23389ab7f..254a2fc9d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. @@ -346,7 +346,6 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #define IM_PRIu64 "llu" #define IM_PRIX64 "llX" #endif -#define IM_TEXTUREID_TO_U64(_TEXID) ((ImU64)(intptr_t)(_TEXID)) //----------------------------------------------------------------------------- // [SECTION] Generic helpers @@ -723,10 +722,10 @@ struct ImSpanAllocator }; // Helper: ImStableVector<> -// Allocating chunks of BLOCK_SIZE items. Objects pointers are never invalidated when growing, only by clear(). +// Allocating chunks of BLOCKSIZE items. Objects pointers are never invalidated when growing, only by clear(). // Important: does not destruct anything! // Implemented only the minimum set of functions we need for it. -template +template struct ImStableVector { int Size = 0; @@ -740,19 +739,19 @@ struct ImStableVector inline void resize(int new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; } inline void reserve(int new_cap) { - new_cap = IM_MEMALIGN(new_cap, BLOCK_SIZE); - int old_count = Capacity / BLOCK_SIZE; - int new_count = new_cap / BLOCK_SIZE; + new_cap = IM_MEMALIGN(new_cap, BLOCKSIZE); + int old_count = Capacity / BLOCKSIZE; + int new_count = new_cap / BLOCKSIZE; if (new_count <= old_count) return; Blocks.resize(new_count); for (int n = old_count; n < new_count; n++) - Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCK_SIZE); + Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCKSIZE); Capacity = new_cap; } - inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; } - inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; } - inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCK_SIZE); void* ptr = &Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; } + inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; } + inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; } + inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCKSIZE); void* ptr = &Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; } }; // Helper: ImPool<> @@ -3994,6 +3993,7 @@ namespace ImGui IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location); IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location); IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); + IMGUI_API ImU64 DebugTextureIDToU64(ImTextureID tex_id); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeDockNode(ImGuiDockNode* node, const char* label); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 41fdf6a4c..25d945d2a 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cc0f47ae6..376331a1a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.5 +// dear imgui, v1.92.6 WIP // (widgets code) /* @@ -1043,6 +1043,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); + if (scrollbar_size_v < 1.0f) + return false; // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) // But we maintain a minimum size in pixel to allow for the user to still aim inside. diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 16bb9817c..26a087017 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -174,7 +174,7 @@ struct ImGui_ImplFreeType_FontSrcBakedData bool ImGui_ImplFreeType_FontSrcData::InitFont(FT_Library ft_library, ImFontConfig* src, ImGuiFreeTypeLoaderFlags extra_font_loader_flags) { - FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)src->FontData, (FT_Long)src->FontDataSize, (FT_Long)src->FontNo, &FtFace); + FT_Error error = FT_New_Memory_Face(ft_library, (const FT_Byte*)src->FontData, (FT_Long)src->FontDataSize, (FT_Long)src->FontNo, &FtFace); if (error != 0) return false; error = FT_Select_Charmap(FtFace, FT_ENCODING_UNICODE);