1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-22 01:54:21 +00:00

Merge branch 'master' into docking (require next commit)

# Conflicts:
#	backends/imgui_impl_glfw.cpp
#	backends/imgui_impl_glfw.h
#	backends/imgui_impl_osx.mm
#	backends/imgui_impl_sdl3.cpp
#	backends/imgui_impl_vulkan.cpp
#	backends/imgui_impl_vulkan.h
#	backends/imgui_impl_win32.cpp
#	imgui.cpp
This commit is contained in:
ocornut 2026-01-14 19:42:11 +01:00
commit 66e08b6575
14 changed files with 152 additions and 91 deletions

View file

@ -29,13 +29,14 @@
// 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.
// 2026-01-05: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
// 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-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)
// 2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
// 2025-11-24: [Helpers] 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.
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
// 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585)
// 2025-09-22: [Docking] Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940)
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
@ -50,8 +51,8 @@
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
// 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
// 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
// 2025-01-06: [Helpers] Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
// 2024-12-11: [Helpers] Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
// 2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
// 2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@ -59,7 +60,7 @@
// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
// 2024-01-19: [Helpers] Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
// 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).
// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)
// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
@ -87,16 +88,16 @@
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
// 2019-04-04: [Helpers] Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
// 2018-08-25: [Helpers] Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.
// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
// 2018-03-03: [Helpers] Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
@ -1816,7 +1817,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
(void)instance;
IM_ASSERT(wd->Surface != VK_NULL_HANDLE);
IM_UNUSED(instance);
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage);
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
@ -1899,6 +1902,7 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
{
IM_UNUSED(instance);
vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
//vkQueueWaitIdle(bd->Queue);
@ -1910,9 +1914,11 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
wd->FrameSemaphores.clear();
vkDestroyRenderPass(device, wd->RenderPass, allocator);
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
*wd = ImGui_ImplVulkanH_Window();
wd->RenderPass = VK_NULL_HANDLE;
wd->Swapchain = VK_NULL_HANDLE;
wd->Width = wd->Height = 0;
wd->FrameIndex = wd->ImageCount = wd->SemaphoreCount = wd->SemaphoreIndex = 0;
//vkDestroySurfaceKHR(instance, wd->Surface, allocator); // v1.92.6 (~2026-01-16): because wd->Surface is user provided we don't attempt to destroy it ourself.
}
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)

View file

@ -179,6 +179,7 @@ struct ImGui_ImplVulkan_RenderState
// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.
//
// You probably do NOT need to use or care about those functions.
// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
// 2) the multi-viewport / platform window implementation needs them internally.
@ -189,8 +190,6 @@ struct ImGui_ImplVulkan_RenderState
// render pass, frame buffers, etc.). You may read this code if you are curious, but
// it is recommended you use your own custom tailored code to do equivalent work.
//
// We don't provide a strong guarantee that we won't change those functions API.
//
// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used
// by the regular ImGui_ImplVulkan_XXX functions.
//-------------------------------------------------------------------------
@ -233,6 +232,7 @@ struct ImGui_ImplVulkanH_Window
{
// Input
bool UseDynamicRendering;
VkSurfaceKHR Surface; // Surface created and destroyed by caller.
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkAttachmentDescription AttachmentDesc; // RenderPass creation: main attachment description.
@ -242,7 +242,6 @@ struct ImGui_ImplVulkanH_Window
int Width; // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()
int Height;
VkSwapchainKHR Swapchain;
VkSurfaceKHR Surface;
VkRenderPass RenderPass;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)

View file

@ -1080,7 +1080,7 @@ WGPUSurface ImGui_ImplWGPU_CreateWGPUSurfaceHelper(ImGui_ImplWGPU_CreateSurfaceI
surface = wgpuInstanceCreateSurface(info->Instance, &surface_descriptor);
}
#else
fprintf(stderr, "'CreateWGPUSurfaceHelper' is not implemented for this platform\n");
IM_ASSERT(0 && "Unsupported WebGPU native platform!");
#endif
return surface;
}

View file

@ -41,6 +41,12 @@ HOW TO UPDATE?
Breaking Changes:
- Commented out legacy names obsoleted in 1.90 (Sept 2023):
- BeginChildFrame() --> BeginChild() with ImGuiChildFlags_FrameStyle flag.
- EndChildFrame() --> EndChild().
- ShowStackToolWindow() --> ShowIDStackToolWindow().
- IM_OFFSETOF() --> offsetof().
- IM_FLOOR() --> IM_TRUNC() [internal, for positive values only]
- Hashing: handling of "###" operator to reset to seed within a string identifier
doesn't include the "###" characters in the output hash anymore:
Before: GetID("Hello###World") == GetID("###World") != GetID("World");
@ -68,6 +74,8 @@ Breaking Changes:
until a shutdown of the owning context or font atlas.
- The fact that handling of `FontDataOwnedByAtlas = false` was broken bypassed
the issue altogether.
- Fixed a crash when trying to use AddFont() with MergeMode=true on a font that
has already been rendered. (#9162) [@ocornut, @cyfewlp]
- Removed ImFontConfig::PixelSnapV added in 1.92 which turns out is unnecessary
(and misdocumented). Post-rescale GlyphOffset is always rounded.
- Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for
@ -97,7 +105,10 @@ Breaking Changes:
- BeginPopupContextItem("foo", 1); // Behavior unchanged (as a courtesy we legacy interpret 1 as ImGuiPopupFlags_MouseButtonRight, will assert if disabling legacy behaviors.
- BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
- BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
- Backends:
- Vulkan: optional ImGui_ImplVulkanH_DestroyWindow() helper used by our example
code does not call vkDestroySurfaceKHR(): because surface is created by caller
of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent. (#9163)
Other Changes:
@ -151,10 +162,28 @@ Other Changes:
end of a line rather than at the beginning of next line. (#8990, #3237)
- Fixed low-level word-wrapping function reading from *text_end when passed
a string range. (#9107) [@achabense]
- Nav:
- Fixed remote/shortcut InputText() not teleporting mouse cursor when
nav cursor is visible and `io.ConfigNavMoveSetMousePos` is enabled.
- Scrollbar: fixed a codepath leading to a divide-by-zero (which would not be
noticeable by user but detected by sanitizers). (#9089) [@judicaelclair]
- InvisibleButton: allow calling with size (0,0) to fit to available content
size. (#9166, #7623)
- Added GetItemFlags() in public API for consistency and to expose generic
flags of last submitted item. (#9127)
- Images:
- Added style.ImageRounding, ImGuiStyleVar_ImageRounding to configure
rounding of Image() widgets. (#2942, #845)
- ImageButton() doesn't use a clamped style.FrameRounding value but instead
adjust inner image rounding when FramePadding > FrameRounding. (#2942, #845)
- Shortcuts:
- IsItemHovered() without ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
doesn't filter out the signal when activated item is a shortcut remote activation;
(which mimicks what's done internally in the ItemHoverable() function). (#9138)
- Fixed tooltip placement being affected for a frame when located over an item
activated by SetNextItemShortcut(). (#9138)
- Error Handling:
- Improve error handling and recovery for EndMenu()/EndCombo(). (#1651, #9165, #8499)
- Debug Tools:
- Debug Log: fixed incorrectly printing characters in IO log when submitting
non-ASCII values to io.AddInputCharacter(). (#9099)

View file

@ -212,11 +212,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@ -226,6 +224,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
@ -256,9 +255,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@ -553,7 +553,7 @@ int main(int, char**)
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
glfwDestroyWindow(window);

View file

@ -203,11 +203,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@ -217,6 +215,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
@ -247,9 +246,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@ -568,7 +568,7 @@ int main(int, char**)
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
SDL_DestroyWindow(window);

View file

@ -205,11 +205,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@ -219,6 +217,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
@ -249,9 +248,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@ -571,7 +571,7 @@ int main(int, char**)
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
SDL_DestroyWindow(window);

View file

@ -201,11 +201,9 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
// Your real engine/app may not use them.
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
@ -215,6 +213,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
// Select Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->Surface = surface;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Select Present Mode
@ -245,9 +244,10 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void CleanupVulkanWindow()
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
{
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
}
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
@ -549,7 +549,7 @@ int main(int, char**)
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkanWindow(&g_MainWindowData);
CleanupVulkan();
::DestroyWindow(hwnd);

View file

@ -402,6 +402,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
- 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/01/08 (1.92.6) - Commented out legacy names obsoleted in 1.90 (Sept 2023): 'BeginChildFrame()' --> 'BeginChild()' with 'ImGuiChildFlags_FrameStyle'. 'EndChildFrame()' --> 'EndChild()'. 'ShowStackToolWindow()' --> 'ShowIDStackToolWindow()'. 'IM_OFFSETOF()' --> 'offsetof()'.
- 2026/01/07 (1.92.6) - Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). Default value has same meaning before and after.
- Refer to GitHub topic #9157 if you have any question.
- Before this version, those functions had a 'ImGuiPopupFlags popup_flags = 1' default value in their function signature.
@ -1365,8 +1366,8 @@ static bool NavScoreItem(ImGuiNavItemData* result, const ImRect& nav
static void NavApplyItemToResult(ImGuiNavItemData* result);
static void NavProcessItem();
static void NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
static ImGuiInputSource NavCalcPreferredRefPosSource();
static ImVec2 NavCalcPreferredRefPos();
static ImGuiInputSource NavCalcPreferredRefPosSource(ImGuiWindowFlags window_type);
static ImVec2 NavCalcPreferredRefPos(ImGuiWindowFlags window_type);
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
static void NavRestoreLayer(ImGuiNavLayer layer);
@ -1498,6 +1499,7 @@ ImGuiStyle::ImGuiStyle()
GrabMinSize = 12.0f; // Minimum width/height of a grab box for slider/scrollbar
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
ImageRounding = 0.0f; // Rounding of Image() calls.
ImageBorderSize = 0.0f; // Thickness of border around tabs.
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
TabBorderSize = 0.0f; // Thickness of border around tabs.
@ -1574,6 +1576,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
GrabRounding = ImTrunc(GrabRounding * scale_factor);
LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
ImageRounding = ImTrunc(ImageRounding * scale_factor);
ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
TabRounding = ImTrunc(TabRounding * scale_factor);
TabMinWidthBase = ImTrunc(TabMinWidthBase * scale_factor);
@ -3674,6 +3677,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ScrollbarPadding) }, // ImGuiStyleVar_ScrollbarPadding
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ImageRounding) }, // ImGuiStyleVar_ImageRounding
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ImageBorderSize) }, // ImGuiStyleVar_ImageBorderSize
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize
@ -4939,7 +4943,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
// Test if another item is active (e.g. being dragged)
const ImGuiID id = g.LastItemData.ID;
if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap && !g.ActiveIdFromShortcut)
{
// When ActiveId == MoveId it means that either:
// - (1) user clicked on void _or_ an item with no id, which triggers moving window (ActiveId is set even when window has _NoMove flag)
@ -6671,10 +6675,8 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 && "Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!");
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
// child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
//if (window_flags & ImGuiWindowFlags_NavFlattened)
// child_flags |= ImGuiChildFlags_NavFlattened;
//if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding) { child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding; }
//if (window_flags & ImGuiWindowFlags_NavFlattened) { child_flags |= ImGuiChildFlags_NavFlattened; }
#endif
if (child_flags & ImGuiChildFlags_AutoResizeX)
child_flags &= ~ImGuiChildFlags_ResizeX;
@ -12884,7 +12886,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
popup_ref.RestoreNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type).
popup_ref.OpenFrameCount = g.FrameCount;
popup_ref.OpenParentId = parent_window->IDStack.back();
popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
popup_ref.OpenPopupPos = NavCalcPreferredRefPos(ImGuiWindowFlags_Popup);
popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopupEx(0x%08X)\n", id);
@ -13138,7 +13140,7 @@ void ImGui::EndPopup()
ImGuiWindow* window = g.CurrentWindow;
if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || g.BeginPopupStack.Size == 0)
{
IM_ASSERT_USER_ERROR(0, "Calling EndPopup() too many times or in wrong window!");
IM_ASSERT_USER_ERROR(0, "Calling EndPopup() in wrong window!");
return;
}
@ -13373,9 +13375,9 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
// as drag and drop tooltips are calling SetNextWindowPos() leading to 'window_pos_set_by_api' being set in Begin().
IM_ASSERT(g.CurrentWindow == window);
const float scale = g.Style.MouseCursorScale;
const ImVec2 ref_pos = NavCalcPreferredRefPos();
const ImVec2 ref_pos = NavCalcPreferredRefPos(ImGuiWindowFlags_Tooltip);
if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource() == ImGuiInputSource_Mouse)
if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource(ImGuiWindowFlags_Tooltip) == ImGuiInputSource_Mouse)
{
ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
if (r_outer.Contains(ImRect(tooltip_pos, tooltip_pos + window->Size)))
@ -13763,6 +13765,8 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
window->NavLastIds[nav_layer] = id;
if (g.LastItemData.ID == id)
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
if (id == g.ActiveIdIsAlive)
g.NavIdIsAlive = true;
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
g.NavHighlightItemUnderNav = true;
@ -14278,31 +14282,29 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
}
}
static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
// Positioning logic altered slightly for remote activation: for Popup we want to use item rect, for Tooltip we leave things alone. (#9138)
// When calling for ImGuiWindowFlags_Popup we use LastItemData.
static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource(ImGuiWindowFlags window_type)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.NavWindow;
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
// Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
if ((window_type & ImGuiWindowFlags_Popup) && activated_shortcut)
return ImGuiInputSource_Keyboard;
if (!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window)
return ImGuiInputSource_Mouse;
else
return ImGuiInputSource_Keyboard; // or Nav in general
}
static ImVec2 ImGui::NavCalcPreferredRefPos()
static ImVec2 ImGui::NavCalcPreferredRefPos(ImGuiWindowFlags window_type)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.NavWindow;
ImGuiInputSource source = NavCalcPreferredRefPosSource();
ImGuiInputSource source = NavCalcPreferredRefPosSource(window_type);
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
if (source != ImGuiInputSource_Mouse && !activated_shortcut && window == NULL)
source = ImGuiInputSource_Mouse;
// Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
if (source == ImGuiInputSource_Mouse)
{
// Mouse (we need a fallback in case the mouse becomes invalid after being used)
@ -14314,8 +14316,9 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
else
{
// When navigation is active and mouse is disabled, pick a position around the bottom left of the currently navigated item
const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
ImRect ref_rect;
if (activated_shortcut)
if (activated_shortcut && (window_type & ImGuiWindowFlags_Popup))
ref_rect = g.LastItemData.NavRect;
else if (window != NULL)
ref_rect = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]);
@ -14516,7 +14519,7 @@ static void ImGui::NavUpdate()
// Update mouse position if requested
// (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied)
if (set_mouse_pos && io.ConfigNavMoveSetMousePos && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
TeleportMousePos(NavCalcPreferredRefPos());
TeleportMousePos(NavCalcPreferredRefPos(ImGuiWindowFlags_Popup));
// [DEBUG]
g.NavScoringDebugCount = 0;

19
imgui.h
View file

@ -1605,7 +1605,7 @@ enum ImGuiSortDirection : ImU8
// All our named keys are >= 512. Keys value 0 to 511 are left unused and were legacy native/opaque key values (< 1.87).
// Support for legacy keys was completely removed in 1.91.5.
// Read details about the 1.87+ transition : https://github.com/ocornut/imgui/issues/4921
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter().
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the latter are submitted via io.AddInputCharacter().
// The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps.
enum ImGuiKey : int
{
@ -1913,6 +1913,7 @@ enum ImGuiStyleVar_
ImGuiStyleVar_ScrollbarPadding, // float ScrollbarPadding
ImGuiStyleVar_GrabMinSize, // float GrabMinSize
ImGuiStyleVar_GrabRounding, // float GrabRounding
ImGuiStyleVar_ImageRounding, // float ImageRounding
ImGuiStyleVar_ImageBorderSize, // float ImageBorderSize
ImGuiStyleVar_TabRounding, // float TabRounding
ImGuiStyleVar_TabBorderSize, // float TabBorderSize
@ -2384,6 +2385,7 @@ struct ImGuiStyle
float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
float ImageRounding; // Rounding of Image() calls.
float ImageBorderSize; // Thickness of border around Image() calls.
float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
float TabBorderSize; // Thickness of border around tabs.
@ -2543,7 +2545,7 @@ struct ImGuiIO
// Options to configure Error Handling and how we handle recoverable errors [EXPERIMENTAL]
// - Error recovery is provided as a way to facilitate:
// - Recovery after a programming error (native code or scripting language - the later tends to facilitate iterating on code while running).
// - Recovery after a programming error (native code or scripting language - the latter tends to facilitate iterating on code while running).
// - Recovery after running an exception handler or any error processing which may skip code after an error has been detected.
// - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
// You not are not supposed to rely on it in the course of a normal application run.
@ -4304,15 +4306,16 @@ namespace ImGui
IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
// OBSOLETED in 1.90.0 (from September 2023)
inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); }
inline void EndChildFrame() { EndChild(); }
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); }
IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
// OBSOLETED in 1.90.0 (from September 2023)
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
//inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); }
//inline void EndChildFrame() { EndChild(); }
//inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); }
// OBSOLETED in 1.89.7 (from June 2023)
//IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() _before_ item.
//-- OBSOLETED in 1.89.4 (from March 2023)
@ -4422,7 +4425,7 @@ typedef ImFontAtlasRect ImFontAtlasCustomRect;
//typedef ImGuiKeyChord ImGuiKeyModFlags; // == int
//enum ImGuiKeyModFlags_ { ImGuiKeyModFlags_None = 0, ImGuiKeyModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiKeyModFlags_Shift = ImGuiMod_Shift, ImGuiKeyModFlags_Alt = ImGuiMod_Alt, ImGuiKeyModFlags_Super = ImGuiMod_Super };
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // OBSOLETED IN 1.90 (now using C++11 standard version)
//#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // OBSOLETED IN 1.90 (now using C++11 standard version)
#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS

View file

@ -8568,6 +8568,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
SliderFloat2("SeparatorTextAlign", (float*)&style.SeparatorTextAlign, 0.0f, 1.0f, "%.2f");
SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%.0f");
SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
SliderFloat("ImageRounding", &style.ImageRounding, 0.0f, 12.0f, "%.0f");
SliderFloat("ImageBorderSize", &style.ImageBorderSize, 0.0f, 1.0f, "%.0f");
SeparatorText("Docking");

View file

@ -3055,6 +3055,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
{
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before.
font = font_cfg_in->DstFont ? font_cfg_in->DstFont : Fonts.back();
ImFontAtlasFontDiscardBakes(this, font, 0); // Need to discard bakes if the font was already used, because baked->FontLoaderDatas[] will change size. (#9162)
}
// Add to list

View file

@ -289,9 +289,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // Positive values only! ImTrunc() is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only!
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
#endif
//#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
// Hint for branch prediction
#if (defined(__cplusplus) && (__cplusplus >= 202002L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L))
@ -4083,7 +4081,7 @@ struct ImFontLoader
IMGUI_API const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype();
#endif
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92] The types are not actually compatible but we provide this as a compile-time error report helper.
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92.0] The types are not actually compatible but we provide this as a compile-time error report helper.
#endif
//-----------------------------------------------------------------------------

View file

@ -836,11 +836,10 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiBut
if (window->SkipItems)
return false;
// Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size.
IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
// Ensure zero-size fits to contents
ImVec2 size = CalcItemSize(ImVec2(size_arg.x != 0.0f ? size_arg.x : -FLT_MIN, size_arg.y != 0.0f ? size_arg.y : -FLT_MIN), 0.0f, 0.0f);
const ImGuiID id = window->GetID(str_id);
ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
ItemSize(size);
if (!ItemAdd(bb, id, NULL, (flags & ImGuiButtonFlags_EnableNav) ? ImGuiItemFlags_None : ImGuiItemFlags_NoNav))
@ -1137,11 +1136,15 @@ void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const Im
return;
// Render
if (g.Style.ImageBorderSize > 0.0f)
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize);
float rounding = g.Style.ImageRounding;
if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col), rounding);
if (rounding > 0.0f)
window->DrawList->AddImageRounded(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col), rounding);
else
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
if (g.Style.ImageBorderSize > 0.0f)
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, ImDrawFlags_None, g.Style.ImageBorderSize);
}
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
@ -1181,10 +1184,14 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
RenderNavCursor(bb, id);
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding);
if (bg_col.w > 0.0f)
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
float image_rounding = ImMax(g.Style.FrameRounding - ImMax(padding.x, padding.y), g.Style.ImageRounding);
if (image_rounding > 0.0f)
window->DrawList->AddImageRounded(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col), image_rounding);
else
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
return pressed;
}
@ -2060,8 +2067,15 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
void ImGui::EndCombo()
{
ImGuiContext& g = *GImGui;
EndPopup();
g.BeginComboDepth--;
char name[16];
ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // FIXME: Move those to helpers?
if (strcmp(g.CurrentWindow->Name, name) != 0)
{
IM_ASSERT_USER_ERROR(0, "Calling EndCombo() in wrong window!");
return;
}
EndPopup();
}
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements
@ -4854,6 +4868,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
SetActiveID(id, window);
SetFocusID(id, window);
FocusWindow(window);
if (input_requested_by_nav)
SetNavCursorVisibleAfterMove();
}
if (g.ActiveId == id)
{
@ -9409,7 +9425,12 @@ void ImGui::EndMenu()
// Nav: When a left move request our menu failed, close ourselves.
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginMenu()/EndMenu() calls
if ((window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) != (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
{
IM_ASSERT_USER_ERROR(0, "Calling EndMenu() in wrong window!");
return;
}
ImGuiWindow* parent_window = window->ParentWindow; // Should always be != NULL is we passed assert.
if (window->BeginCount == window->BeginCountPreviousFrame)
if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet())
@ -10397,7 +10418,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
ImGuiTabBar* tab_bar = g.CurrentTabBar;
if (tab_bar == NULL)
{
IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!");
IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
return false;
}
IM_ASSERT((flags & ImGuiTabItemFlags_Button) == 0); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead!