1
0
mirror of https://github.com/ocornut/imgui.git synced 2025-02-26 22:59:19 +01:00

Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_vulkan.cpp
#	imgui_internal.h
This commit is contained in:
ocornut 2025-01-13 14:30:57 +01:00
commit d0d571e0d7
12 changed files with 122 additions and 53 deletions

View File

@ -154,6 +154,7 @@ bool ImGui_ImplMetal_Init(id<MTLDevice> device)
void ImGui_ImplMetal_Shutdown() void ImGui_ImplMetal_Shutdown()
{ {
ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
IM_UNUSED(bd);
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGui_ImplMetal_ShutdownMultiViewportSupport(); ImGui_ImplMetal_ShutdownMultiViewportSupport();
ImGui_ImplMetal_DestroyDeviceObjects(); ImGui_ImplMetal_DestroyDeviceObjects();

View File

@ -28,6 +28,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 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. // 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) // 2024-12-11: 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-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)
@ -1052,8 +1053,9 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
check_vk_result(err); check_vk_result(err);
} }
if (v->DescriptorPoolSize) if (v->DescriptorPoolSize != 0)
{ {
IM_ASSERT(v->DescriptorPoolSize > IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE);
VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize }; VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;

View File

@ -62,14 +62,16 @@
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#endif #endif
// Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
// It is expected that as early as Q1 2025 the backend will use a few more descriptors. Use this value + number of desired calls to ImGui_ImplVulkan_AddTexture().
#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (1) // Minimum per atlas
// Initialization data, for ImGui_ImplVulkan_Init() // Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!] // [Please zero-clear before use!]
// - About descriptor pool: // - About descriptor pool:
// - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
// and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors. // and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you. // - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
// - Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
// - It is expected that as early as Q1 2025 the backend will use a few more descriptors, so aim at 10 + number of desierd calls to ImGui_ImplVulkan_AddTexture().
// - About dynamic rendering: // - About dynamic rendering:
// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. // - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
struct ImGui_ImplVulkan_InitInfo struct ImGui_ImplVulkan_InitInfo

View File

@ -43,8 +43,19 @@ Breaking changes:
Other changes: Other changes:
- Fixed issues with IsItemDeactivated() and IsItemDeactivatedAfterEdit() not
emitting a reliable signal when an item is deactivated externally: e.g.
via an explicit clear of focus, clear of active id, opening of modal etc.
(#5184, #5904, #6766, #8303, #8004)
- It used to work when the interruption happened in the frame before the
active item as submitted, but not after. It should work in both cases now.
- While this is not specific to a certain widgets, typically it would
mostly be noticeable on InputText() because it keeps ActiveId for a
longer time while allowing other interaction to happen.
- Error Handling: Fixed bugs recovering from within a table that created - Error Handling: Fixed bugs recovering from within a table that created
a child window, and from nested child windows. (#1651) a child window, and from nested child windows. (#1651)
- Error Handling: Turned common EndTable() and other TableXXX functions
fail cases into a recoverable error. (#1651, #8314)
- InputText: Fixed a bug where character replacements performed from a callback - InputText: Fixed a bug where character replacements performed from a callback
were not applied when pasting from clipbard. (#8229) were not applied when pasting from clipbard. (#8229)
- InputText: Fixed issue when activating a ReadOnly field when the underlying - InputText: Fixed issue when activating a ReadOnly field when the underlying
@ -79,6 +90,10 @@ Other changes:
platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF]
- Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions - Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions
primarily for the purpose of making our examples simpler. primarily for the purpose of making our examples simpler.
- Backends: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify
how many image sampler descriptors are expected to be available in the provided
descriptor pool. Current backend needs 1 but it is expected that by end of Q1 2025
this number will grow (will staying a very small number). (#6642)
- Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. - Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState.
Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590) Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590)
- Backends: DX10: Expose ImGui_ImplDX10_RenderState for completeness. (#6969, #5834, #7468, #3590) - Backends: DX10: Expose ImGui_ImplDX10_RenderState for completeness. (#6969, #5834, #7468, #3590)
@ -156,11 +171,12 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
Breaking changes: Breaking changes:
- Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before). - 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). - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). Use IsKeyDown() instead.
- io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022). - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
- Pre-1.87 backends are not supported: - 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.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. - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
- you can use IsKeyDown() instead of reading from io.KeysDown[].
- For more references: - For more references:
- read 1.87 and 1.88 part of API BREAKING CHANGES in imgui.cpp or read Changelog for 1.87 and 1.88. - read 1.87 and 1.88 part of API BREAKING CHANGES in imgui.cpp or read Changelog for 1.87 and 1.88.
- read https://github.com/ocornut/imgui/issues/4921 - read https://github.com/ocornut/imgui/issues/4921
@ -2656,6 +2672,7 @@ Breaking Changes:
- For all calls to IO new functions, the Dear ImGui context should be bound/current. - For all calls to IO new functions, the Dear ImGui context should be bound/current.
- Reworked IO keyboard input API: (#4921, #2625, #3724) [@thedmd, @ocornut] - Reworked IO keyboard input API: (#4921, #2625, #3724) [@thedmd, @ocornut]
- Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays.
- You can use IsKeyDown() instead of reading from io.KeysDown[].
- For keyboard modifiers, you can call io.AddKeyEvent() with ImGuiKey_ModXXX values, - For keyboard modifiers, you can call io.AddKeyEvent() with ImGuiKey_ModXXX values,
obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. obsoleting writing directly to io.KeyCtrl, io.KeyShift etc.
- Added io.SetKeyEventNativeData() function (optional) to pass native and old legacy indices. - Added io.SetKeyEventNativeData() function (optional) to pass native and old legacy indices.

View File

@ -189,17 +189,18 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
} }
// Create Descriptor Pool // Create Descriptor Pool
// The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
// If you wish to load e.g. additional textures you may need to alter pools sizes.
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
{ {
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
}; };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1; pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes; pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);

View File

@ -177,17 +177,18 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
} }
// Create Descriptor Pool // Create Descriptor Pool
// The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
// If you wish to load e.g. additional textures you may need to alter pools sizes.
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
{ {
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
}; };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1; pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes; pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);

View File

@ -182,17 +182,18 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
} }
// Create Descriptor Pool // Create Descriptor Pool
// The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
// If you wish to load e.g. additional textures you may need to alter pools sizes.
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
{ {
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
}; };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1; pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes; pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);

View File

@ -178,17 +178,18 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
} }
// Create Descriptor Pool // Create Descriptor Pool
// The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
// If you wish to load e.g. additional textures you may need to alter pools sizes.
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
{ {
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE },
}; };
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1; pool_info.maxSets = 0;
for (VkDescriptorPoolSize& pool_size : pool_sizes)
pool_info.maxSets += pool_size.descriptorCount;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes; pool_info.pPoolSizes = pool_sizes;
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);

View File

@ -658,7 +658,7 @@ CODE
- Backend writing to io.MouseHoveredViewport -> backend should call io.AddMouseViewportEvent() [Docking branch w/ multi-viewports only] - Backend writing to io.MouseHoveredViewport -> backend should call io.AddMouseViewportEvent() [Docking branch w/ multi-viewports only]
note: for all calls to IO new functions, the Dear ImGui context should be bound/current. note: for all calls to IO new functions, the Dear ImGui context should be bound/current.
read https://github.com/ocornut/imgui/issues/4921 for details. read https://github.com/ocornut/imgui/issues/4921 for details.
- 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unnecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details. - 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(), ImGui::IsKeyDown(). Removed GetKeyIndex(), now unnecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details.
- IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX)
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX)
- Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to stil function with legacy key codes). - Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to stil function with legacy key codes).
@ -4002,9 +4002,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
ActiveIdSource = ImGuiInputSource_None; ActiveIdSource = ImGuiInputSource_None;
ActiveIdMouseButton = -1; ActiveIdMouseButton = -1;
ActiveIdPreviousFrame = 0; ActiveIdPreviousFrame = 0;
ActiveIdPreviousFrameIsAlive = false; memset(&DeactivatedItemData, 0, sizeof(DeactivatedItemData));
ActiveIdPreviousFrameHasBeenEditedBefore = false;
ActiveIdPreviousFrameWindow = NULL;
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation)); memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
LastActiveId = 0; LastActiveId = 0;
LastActiveIdTimer = 0.0f; LastActiveIdTimer = 0.0f;
@ -4270,7 +4268,7 @@ void ImGui::Shutdown()
g.WindowsById.Clear(); g.WindowsById.Clear();
g.NavWindow = NULL; g.NavWindow = NULL;
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; g.ActiveIdWindow = NULL;
g.MovingWindow = NULL; g.MovingWindow = NULL;
g.KeysRoutingTable.Clear(); g.KeysRoutingTable.Clear();
@ -4460,6 +4458,13 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.MovingWindow = NULL; g.MovingWindow = NULL;
} }
// Store deactivate data
ImGuiDeactivatedItemData* deactivated_data = &g.DeactivatedItemData;
deactivated_data->ID = g.ActiveId;
deactivated_data->ElapseFrame = (g.LastItemData.ID == g.ActiveId) ? g.FrameCount : g.FrameCount + 1; // FIXME: OK to use LastItemData?
deactivated_data->HasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
deactivated_data->IsAlive = (g.ActiveIdIsAlive == g.ActiveId);
// This could be written in a more general way (e.g associate a hook to ActiveId), // This could be written in a more general way (e.g associate a hook to ActiveId),
// but since this is currently quite an exception we'll leave it as is. // but since this is currently quite an exception we'll leave it as is.
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID() // One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
@ -5378,11 +5383,8 @@ void ImGui::NewFrame()
g.ActiveIdTimer += g.IO.DeltaTime; g.ActiveIdTimer += g.IO.DeltaTime;
g.LastActiveIdTimer += g.IO.DeltaTime; g.LastActiveIdTimer += g.IO.DeltaTime;
g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
g.ActiveIdIsAlive = 0; g.ActiveIdIsAlive = 0;
g.ActiveIdHasBeenEditedThisFrame = false; g.ActiveIdHasBeenEditedThisFrame = false;
g.ActiveIdPreviousFrameIsAlive = false;
g.ActiveIdIsJustActivated = false; g.ActiveIdIsJustActivated = false;
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
g.TempInputId = 0; g.TempInputId = 0;
@ -5391,6 +5393,9 @@ void ImGui::NewFrame()
g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingNavDirMask = 0x00;
g.ActiveIdUsingAllKeyboardKeys = false; g.ActiveIdUsingAllKeyboardKeys = false;
} }
if (g.DeactivatedItemData.ElapseFrame < g.FrameCount)
g.DeactivatedItemData.ID = 0;
g.DeactivatedItemData.IsAlive = false;
// Record when we have been stationary as this state is preserved while over same item. // Record when we have been stationary as this state is preserved while over same item.
// FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values.
@ -6101,13 +6106,13 @@ bool ImGui::IsItemDeactivated()
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated) if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID); return (g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 && g.DeactivatedItemData.ElapseFrame >= g.FrameCount);
} }
bool ImGui::IsItemDeactivatedAfterEdit() bool ImGui::IsItemDeactivatedAfterEdit()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore)); return IsItemDeactivated() && g.DeactivatedItemData.HasBeenEditedBefore;
} }
// == (GetItemID() == GetFocusID() && GetFocusID() != 0) // == (GetItemID() == GetFocusID() && GetFocusID() != 0)
@ -11115,8 +11120,8 @@ void ImGui::KeepAliveID(ImGuiID id)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ActiveId == id) if (g.ActiveId == id)
g.ActiveIdIsAlive = id; g.ActiveIdIsAlive = id;
if (g.ActiveIdPreviousFrame == id) if (g.DeactivatedItemData.ID == id)
g.ActiveIdPreviousFrameIsAlive = true; g.DeactivatedItemData.IsAlive = true;
} }
// Declare item bounding box for clipping and interaction. // Declare item bounding box for clipping and interaction.
@ -11201,6 +11206,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG] // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
#endif #endif
if (id != 0 && g.DeactivatedItemData.ID == id)
g.DeactivatedItemData.ElapseFrame = g.FrameCount;
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
if (is_rect_visible) if (is_rect_visible)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
@ -11560,7 +11568,7 @@ void ImGui::BeginGroup()
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupIsSameLine = window->DC.IsSameLine; group_data.BackupIsSameLine = window->DC.IsSameLine;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
group_data.EmitItem = true; group_data.EmitItem = true;
window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x; window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
@ -11611,11 +11619,11 @@ void ImGui::EndGroup()
// Also if you grep for LastItemId you'll notice it is only used in that context. // Also if you grep for LastItemId you'll notice it is only used in that context.
// (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.) // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); const bool group_contains_deactivated_id = (group_data.BackupDeactivatedIdIsAlive == false) && (g.DeactivatedItemData.IsAlive == true);
if (group_contains_curr_active_id) if (group_contains_curr_active_id)
g.LastItemData.ID = g.ActiveId; g.LastItemData.ID = g.ActiveId;
else if (group_contains_prev_active_id) else if (group_contains_deactivated_id)
g.LastItemData.ID = g.ActiveIdPreviousFrame; g.LastItemData.ID = g.DeactivatedItemData.ID;
g.LastItemData.Rect = group_bb; g.LastItemData.Rect = group_bb;
// Forward Hovered flag // Forward Hovered flag
@ -11629,7 +11637,7 @@ void ImGui::EndGroup()
// Forward Deactivated flag // Forward Deactivated flag
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) if (group_contains_deactivated_id)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
g.GroupStack.pop_back(); g.GroupStack.pop_back();

View File

@ -29,7 +29,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.91.7 WIP" #define IMGUI_VERSION "1.91.7 WIP"
#define IMGUI_VERSION_NUM 19164 #define IMGUI_VERSION_NUM 19165
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch

View File

@ -140,6 +140,7 @@ struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum) struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function.
struct ImGuiDockContext; // Docking system context struct ImGuiDockContext; // Docking system context
struct ImGuiDockRequest; // Docking system dock/undock queued request struct ImGuiDockRequest; // Docking system dock/undock queued request
struct ImGuiDockNode; // Docking system node (hold a list of Windows OR two child dock nodes) struct ImGuiDockNode; // Docking system node (hold a list of Windows OR two child dock nodes)
@ -1081,7 +1082,7 @@ struct IMGUI_API ImGuiGroupData
ImVec2 BackupCurrLineSize; ImVec2 BackupCurrLineSize;
float BackupCurrLineTextBaseOffset; float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive; ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdPreviousFrameIsAlive; bool BackupDeactivatedIdIsAlive;
bool BackupHoveredIdIsAlive; bool BackupHoveredIdIsAlive;
bool BackupIsSameLine; bool BackupIsSameLine;
bool EmitItem; bool EmitItem;
@ -1266,11 +1267,11 @@ struct ImGuiNextItemData
struct ImGuiLastItemData struct ImGuiLastItemData
{ {
ImGuiID ID; ImGuiID ID;
ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ (called 'InFlags' before v1.91.4).
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
ImRect Rect; // Full rectangle ImRect Rect; // Full rectangle
ImRect NavRect; // Navigation scoring rectangle (not displayed) ImRect NavRect; // Navigation scoring rectangle (not displayed)
// Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags ar set. // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags are set.
ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set. ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set.
ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set.. ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set..
ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set.. ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set..
@ -1333,6 +1334,15 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
struct ImGuiDeactivatedItemData
{
ImGuiID ID;
int ElapseFrame;
bool HasBeenEditedBefore;
bool IsAlive;
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Popup support // [SECTION] Popup support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2302,9 +2312,7 @@ struct ImGuiContext
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive; ImGuiDeactivatedItemData DeactivatedItemData;
bool ActiveIdPreviousFrameHasBeenEditedBefore;
ImGuiWindow* ActiveIdPreviousFrameWindow;
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX. ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.

View File

@ -1337,7 +1337,11 @@ void ImGui::EndTable()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "EndTable() call should only be done while in BeginTable() scope!");
return;
}
// This assert would be very useful to catch a common error... unfortunately it would probably trigger in some // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some
// cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border) // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border)
@ -1560,8 +1564,12 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); if (table == NULL)
IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!"); {
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()"); IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
if (table->DeclColumnsCount >= table->ColumnsCount) if (table->DeclColumnsCount >= table->ColumnsCount)
{ {
@ -1634,7 +1642,11 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
@ -1711,9 +1723,11 @@ void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL); if (table == NULL)
if (!table) {
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return; return;
}
IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above
if (column_n < 0) if (column_n < 0)
column_n = table->CurrentColumn; column_n = table->CurrentColumn;
@ -3034,7 +3048,11 @@ void ImGui::TableHeadersRow()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
// Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make // Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make
// it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this. // it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this.
@ -3079,7 +3097,12 @@ void ImGui::TableHeader(const char* label)
return; return;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->CurrentColumn != -1); IM_ASSERT(table->CurrentColumn != -1);
const int column_n = table->CurrentColumn; const int column_n = table->CurrentColumn;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@ -3254,7 +3277,11 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImDrawList* draw_list = window->DrawList; ImDrawList* draw_list = window->DrawList;
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); if (table == NULL)
{
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
return;
}
IM_ASSERT(table->CurrentRow == -1 && "Must be first row"); IM_ASSERT(table->CurrentRow == -1 && "Must be first row");
if (max_label_width == 0.0f) if (max_label_width == 0.0f)