Merge branch 'docking' of git.alexdelcamp.fr:Alexandre_1a/imgui into docking

Added personals changes (modules)
This commit is contained in:
Alexandre 2026-09-28 16:07:56 +02:00
commit d7cce3ad50
68 changed files with 1185 additions and 550 deletions

View File

@ -14,6 +14,7 @@ body:
attributes: attributes:
value: | value: |
**Prerequisites:** **Prerequisites:**
- I am not using a LLM to think or write for me. Please distill information to what's necessary and meaningful.
- I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md). - I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md).
- I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice). - I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice).
- I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue). - I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue).

View File

@ -6,7 +6,7 @@
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors. 3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
4. PLEASE DO NOT SUBMIT AI SLOP OR AUTOMATED REPORTS. Submissions that are lacking proper human review/judgement before being passed to us are not welcome. 4. PLEASE DO NOT SUBMIT AI SLOP OR AUTOMATED AI REPORTS. Submissions that are lacking proper human review/judgement before being passed to us are not welcome. Do not let a LLM AI write most of the text for you.
5. Clear this template before submitting your PR. 5. Clear this template before submitting your PR.

View File

@ -5,6 +5,7 @@
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX10_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -18,6 +19,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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378) // 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'. // 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
@ -101,6 +103,11 @@ static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplDX10_RenderState* ImGui_ImplDX10_GetRenderState()
{
return (ImGui_ImplDX10_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Forward Declarations // Forward Declarations
static void ImGui_ImplDX10_InitMultiViewportSupport(); static void ImGui_ImplDX10_InitMultiViewportSupport();
static void ImGui_ImplDX10_ShutdownMultiViewportSupport(); static void ImGui_ImplDX10_ShutdownMultiViewportSupport();
@ -112,8 +119,8 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
// Setup viewport // Setup viewport
D3D10_VIEWPORT vp = {}; D3D10_VIEWPORT vp = {};
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0; vp.TopLeftX = vp.TopLeftY = 0;
@ -767,10 +774,12 @@ static void ImGui_ImplDX10_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
} }
} }
static void ImGui_ImplDX10_RenderViewport(ImGuiViewport* viewport, void*) static void ImGui_ImplDX10_RenderWindow(ImGuiViewport* viewport, void*)
{ {
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
ImGui_ImplDX10_ViewportData* vd = (ImGui_ImplDX10_ViewportData*)viewport->RendererUserData; ImGui_ImplDX10_ViewportData* vd = (ImGui_ImplDX10_ViewportData*)viewport->RendererUserData;
if (vd->RTView == nullptr) // Swap chain creation or resize failed (e.g. device removed)
return;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
bd->pd3dDevice->OMSetRenderTargets(1, &vd->RTView, nullptr); bd->pd3dDevice->OMSetRenderTargets(1, &vd->RTView, nullptr);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
@ -791,7 +800,7 @@ void ImGui_ImplDX10_InitMultiViewportSupport()
platform_io.Renderer_CreateWindow = ImGui_ImplDX10_CreateWindow; platform_io.Renderer_CreateWindow = ImGui_ImplDX10_CreateWindow;
platform_io.Renderer_DestroyWindow = ImGui_ImplDX10_DestroyWindow; platform_io.Renderer_DestroyWindow = ImGui_ImplDX10_DestroyWindow;
platform_io.Renderer_SetWindowSize = ImGui_ImplDX10_SetWindowSize; platform_io.Renderer_SetWindowSize = ImGui_ImplDX10_SetWindowSize;
platform_io.Renderer_RenderWindow = ImGui_ImplDX10_RenderViewport; platform_io.Renderer_RenderWindow = ImGui_ImplDX10_RenderWindow;
platform_io.Renderer_SwapBuffers = ImGui_ImplDX10_SwapBuffers; platform_io.Renderer_SwapBuffers = ImGui_ImplDX10_SwapBuffers;
} }

View File

@ -5,6 +5,7 @@
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX10_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -46,5 +47,6 @@ struct ImGui_ImplDX10_RenderState
//ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear) //ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest) //ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
}; };
IMGUI_IMPL_API ImGui_ImplDX10_RenderState* ImGui_ImplDX10_GetRenderState();
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -5,7 +5,7 @@
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX11_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -107,6 +107,11 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplDX11_RenderState* ImGui_ImplDX11_GetRenderState()
{
return (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Forward Declarations // Forward Declarations
static void ImGui_ImplDX11_InitMultiViewportSupport(); static void ImGui_ImplDX11_InitMultiViewportSupport();
static void ImGui_ImplDX11_ShutdownMultiViewportSupport(); static void ImGui_ImplDX11_ShutdownMultiViewportSupport();
@ -118,8 +123,8 @@ static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11D
// Setup viewport // Setup viewport
D3D11_VIEWPORT vp = {}; D3D11_VIEWPORT vp = {};
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x; vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y; vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0; vp.TopLeftX = vp.TopLeftY = 0;
@ -802,6 +807,8 @@ static void ImGui_ImplDX11_RenderWindow(ImGuiViewport* viewport, void*)
{ {
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData; ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData;
if (vd->RTView == nullptr) // Swap chain creation or resize failed (e.g. device removed)
return;
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
bd->pd3dDeviceContext->OMSetRenderTargets(1, &vd->RTView, nullptr); bd->pd3dDeviceContext->OMSetRenderTargets(1, &vd->RTView, nullptr);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))

View File

@ -5,7 +5,7 @@
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX11_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
@ -49,5 +49,6 @@ struct ImGui_ImplDX11_RenderState
//ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear) //ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest) //ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
}; };
IMGUI_IMPL_API ImGui_ImplDX11_RenderState* ImGui_ImplDX11_GetRenderState();
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -5,7 +5,7 @@
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX12_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// FIXME: The transition from removing a viewport and moving the window in an existing hosted viewport tends to flicker. // FIXME: The transition from removing a viewport and moving the window in an existing hosted viewport tends to flicker.
@ -23,6 +23,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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-05: DirectX12: *BREAKING CHANGE* Removed support for legacy `ImGui_ImplDX12_Init()` signature obsoleted in 1.91.6 (2024-11-15) because it needed to forcefully disable support for ImGuiBackendFlags_RendererHasTextures. (#9487) // 2026-08-05: DirectX12: *BREAKING CHANGE* Removed support for legacy `ImGui_ImplDX12_Init()` signature obsoleted in 1.91.6 (2024-11-15) because it needed to forcefully disable support for ImGuiBackendFlags_RendererHasTextures. (#9487)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2025-10-23: [Docking] DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#8961, #9025) // 2025-10-23: [Docking] DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#8961, #9025)
@ -133,6 +134,11 @@ static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplDX12_RenderState* ImGui_ImplDX12_GetRenderState()
{
return (ImGui_ImplDX12_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Buffers used during the rendering of a frame // Buffers used during the rendering of a frame
struct ImGui_ImplDX12_RenderBuffers struct ImGui_ImplDX12_RenderBuffers
{ {
@ -258,8 +264,8 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
// Setup viewport // Setup viewport
D3D12_VIEWPORT vp = {}; D3D12_VIEWPORT vp = {};
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x; vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y; vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0.0f; vp.TopLeftX = vp.TopLeftY = 0.0f;
@ -1255,6 +1261,8 @@ static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void*)
{ {
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)viewport->RendererUserData; ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)viewport->RendererUserData;
if (vd->SwapChain == nullptr)
return;
ImGui_ImplDX12_FrameContext* frame_context = ImGui_WaitForNextFrameContext(vd); ImGui_ImplDX12_FrameContext* frame_context = ImGui_WaitForNextFrameContext(vd);
UINT back_buffer_idx = vd->SwapChain->GetCurrentBackBufferIndex(); UINT back_buffer_idx = vd->SwapChain->GetCurrentBackBufferIndex();

View File

@ -5,7 +5,7 @@
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX12_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification. // The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
@ -75,6 +75,7 @@ struct ImGui_ImplDX12_RenderState
ID3D12Device* Device; ID3D12Device* Device;
ID3D12GraphicsCommandList* CommandList; ID3D12GraphicsCommandList* CommandList;
}; };
IMGUI_IMPL_API ImGui_ImplDX12_RenderState* ImGui_ImplDX12_GetRenderState();
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// Legacy initialization API Obsoleted in 1.91.5 // Legacy initialization API Obsoleted in 1.91.5

View File

@ -32,6 +32,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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-15: [Docking] Fixed applying mouse cursor shapes to secondary viewports (broken in 1.92.6, 2025-12-10).
// 2026-04-21: Added a Win32-specific implementation of ImGui_ImplGlfw_GetContentScaleXXXX functions for legacy GLFW 3.2. // 2026-04-21: Added a Win32-specific implementation of ImGui_ImplGlfw_GetContentScaleXXXX functions for legacy GLFW 3.2.
// 2026-03-25: Mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. Amend change from 2025-12-10. // 2026-03-25: Mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. Amend change from 2025-12-10.
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225) // 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
@ -1002,6 +1003,15 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
#if GLFW_HAS_CREATECURSOR
GLFWcursor* set_mouse_cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
if (bd->LastMouseCursor == set_mouse_cursor)
set_mouse_cursor = NULL;
else
bd->LastMouseCursor = set_mouse_cursor;
#endif
for (int n = 0; n < platform_io.Viewports.Size; n++) for (int n = 0; n < platform_io.Viewports.Size; n++)
{ {
GLFWwindow* window = (GLFWwindow*)platform_io.Viewports[n]->PlatformHandle; GLFWwindow* window = (GLFWwindow*)platform_io.Viewports[n]->PlatformHandle;
@ -1019,12 +1029,8 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
// Show OS mouse cursor // Show OS mouse cursor
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
#if GLFW_HAS_CREATECURSOR #if GLFW_HAS_CREATECURSOR
GLFWcursor* cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]; if (set_mouse_cursor)
if (bd->LastMouseCursor != cursor) glfwSetCursor(window, set_mouse_cursor);
{
glfwSetCursor(window, cursor);
bd->LastMouseCursor = cursor;
}
#endif #endif
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
} }
@ -1422,6 +1428,7 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
glfwMakeContextCurrent(vd->Window); glfwMakeContextCurrent(vd->Window);
glfwSwapInterval(0); glfwSwapInterval(0);
} }
bd->LastMouseCursor = nullptr; // Invalidate so that cursor is set again
} }
static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport) static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)

View File

@ -18,6 +18,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)
// 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-06: Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856) // 2026-08-06: Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856)
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381) // 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
@ -172,8 +173,8 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
{ {
.originX = 0.0, .originX = 0.0,
.originY = 0.0, .originY = 0.0,
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x), .width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y), .height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
.znear = 0.0, .znear = 0.0,
.zfar = 1.0 .zfar = 1.0
}; };
@ -212,8 +213,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
MetalContext* ctx = bd->SharedMetalContext; MetalContext* ctx = bd->SharedMetalContext;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0) if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return; return;

View File

@ -21,6 +21,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)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-06: Metal 4: fixed resizing windows losing framebuffer scale. (#6828, #8856) // 2026-08-06: Metal 4: fixed resizing windows losing framebuffer scale. (#6828, #8856)
// 2026-07-07: Metal 4: Added metal-cpp support. (#9461) // 2026-07-07: Metal 4: Added metal-cpp support. (#9461)
// 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458) // 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458)
@ -181,8 +182,8 @@ static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4Comm
{ {
.originX = 0.0, .originX = 0.0,
.originY = 0.0, .originY = 0.0,
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x), .width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y), .height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
.znear = 0.0, .znear = 0.0,
.zfar = 1.0 .zfar = 1.0
}; };
@ -229,8 +230,8 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id<MTL4CommandBuffer
MetalContext* ctx = bd->SharedMetalContext; MetalContext* ctx = bd->SharedMetalContext;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0) if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return; return;

View File

@ -28,6 +28,8 @@
// 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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-17: OpenGL: Added support for platform_io.DrawCallback_SetSamplerFromTex. (#9378)
// 2026-09-07: OpenGL: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473) // 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295) // 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
@ -137,6 +139,8 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
bd->UseTexParameterToSetSampler = false;
bd->NextSampler = GL_LINEAR; bd->NextSampler = GL_LINEAR;
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
@ -163,9 +167,13 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
} }
// Draw callbacks // Draw callbacks
// - IMPORTANT: Using DrawCallback_SetSamplerLinear/DrawCallback_SetSamplerNearest will trash glTexParameteri() values for the texture!!
// We cannot decently backup/restore that state because glGetTexParameteriv() is slow on many setups.
// - Using DrawCallback_SetSamplerFromTex will basically instruct the backend to use existing glTexParameteri() values without modifying anything, which is the initial state.
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way. static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = false; }
// OpenGL2 Render function. // OpenGL2 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly. // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
@ -174,8 +182,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width == 0 || fb_height == 0) if (fb_width == 0 || fb_height == 0)
return; return;
@ -368,6 +376,7 @@ bool ImGui_ImplOpenGL2_Init()
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState; platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear; platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest; platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest;
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplOpenGL2_DrawCallback_SetSamplerFromTex;
return true; return true;
} }

View File

@ -7,6 +7,7 @@
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!] // [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplOpenGL3_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES: // About WebGL/ES:
@ -25,6 +26,8 @@
// 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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-17: OpenGL: Added support for platform_io.DrawCallback_SetSamplerFromTex. (#9378)
// 2026-09-07: OpenGL: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473) // 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
// 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering. // 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering.
// 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577) // 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577)
@ -275,6 +278,11 @@ static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState()
{
return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Forward Declarations // Forward Declarations
static void ImGui_ImplOpenGL3_InitMultiViewportSupport(); static void ImGui_ImplOpenGL3_InitMultiViewportSupport();
static void ImGui_ImplOpenGL3_ShutdownMultiViewportSupport(); static void ImGui_ImplOpenGL3_ShutdownMultiViewportSupport();
@ -391,9 +399,12 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_Impl
glUniform1i(bd->AttribLocationTex, 0); glUniform1i(bd->AttribLocationTex, 0);
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
(void)render_state; render_state->UseBindSampler = bd->HasBindSampler;
render_state->UseTexParameterFilter = false;
render_state->CurrentSampler = 0;
render_state->CurrentTexParameterFilter = 0;
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (render_state->UseBindSampler) if (bd->HasBindSampler && render_state->UseBindSampler)
{ {
render_state->CurrentSampler = bd->TexSamplers[0]; render_state->CurrentSampler = bd->TexSamplers[0];
glBindSampler(0, render_state->CurrentSampler); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise. glBindSampler(0, render_state->CurrentSampler); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
@ -416,16 +427,15 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_Impl
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)));
} }
// Draw callbacks static void ImGui_ImplOpenGL3_DrawCallback_SetSampler(unsigned int sampler_idx, unsigned int tex_parameter_filter)
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*)
{ {
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState(); ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
IM_UNUSED(sampler_idx);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (bd->HasBindSampler) if (bd->HasBindSampler && render_state->UseBindSampler)
{ {
render_state->CurrentSampler = bd->TexSamplers[0]; render_state->CurrentSampler = bd->TexSamplers[sampler_idx];
render_state->UseTexParameterFilter = false; render_state->UseTexParameterFilter = false;
glBindSampler(0, render_state->CurrentSampler); glBindSampler(0, render_state->CurrentSampler);
} }
@ -433,26 +443,30 @@ static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, c
#endif #endif
{ {
render_state->UseTexParameterFilter = true; render_state->UseTexParameterFilter = true;
render_state->CurrentTexParameterFilter = GL_LINEAR; render_state->CurrentTexParameterFilter = tex_parameter_filter;
} }
} }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*)
// Draw callbacks
// - IMPORTANT: Using DrawCallback_SetSamplerLinear/DrawCallback_SetSamplerNearest will trash glTexParameteri() values for the texture if used on a GL context not supporting glBindSampler()!!
// We cannot decently backup/restore that state because glGetTexParameteriv() is slow on many setups.
// - Using DrawCallback_SetSamplerFromTex will basically instruct the backend to use existing glTexParameteri() values without modifying anything.
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_DrawCallback_SetSampler(0, GL_LINEAR); }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_DrawCallback_SetSampler(1, GL_NEAREST); }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*)
{ {
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState(); ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (bd->HasBindSampler) if (bd->HasBindSampler)
{ {
render_state->CurrentSampler = bd->TexSamplers[1]; render_state->CurrentSampler = 0;
render_state->UseTexParameterFilter = false; glBindSampler(0, 0);
glBindSampler(0, render_state->CurrentSampler);
} }
else
#endif #endif
{ render_state->UseBindSampler = false;
render_state->UseTexParameterFilter = true; render_state->UseTexParameterFilter = false;
render_state->CurrentTexParameterFilter = GL_NEAREST;
}
} }
// OpenGL3 Render function. // OpenGL3 Render function.
@ -461,8 +475,8 @@ static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*,
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0) if (fb_width <= 0 || fb_height <= 0)
return; return;
@ -526,11 +540,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
// Setup render state structure (for callbacks and custom texture bindings) // Setup render state structure (for callbacks and custom texture bindings)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplOpenGL3_RenderState render_state; ImGui_ImplOpenGL3_RenderState render_state = {};
render_state.UseBindSampler = bd->HasBindSampler;
render_state.UseTexParameterFilter = false;
render_state.CurrentSampler = 0;
render_state.CurrentTexParameterFilter = 0;
platform_io.Renderer_RenderState = &render_state; platform_io.Renderer_RenderState = &render_state;
ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object); ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object);
@ -1101,6 +1111,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL3_DrawCallback_ResetRenderState; platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL3_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear; platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest; platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest;
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplOpenGL3_DrawCallback_SetSamplerFromTex;
// Store GLSL version string so we can refer to it later in case we recreate shaders. // Store GLSL version string so we can refer to it later in case we recreate shaders.
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure. // Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.

View File

@ -7,6 +7,7 @@
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!] // [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplOpenGL3_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES: // About WebGL/ES:
@ -73,10 +74,9 @@ struct ImGui_ImplOpenGL3_RenderState
{ {
bool UseBindSampler; bool UseBindSampler;
bool UseTexParameterFilter; bool UseTexParameterFilter;
unsigned int CurrentSampler; // (GLuint) Used if UseBindSampler == true, otherwise always 0 unsigned int CurrentSampler; // (GLuint) Used if UseBindSampler == true (and are available), otherwise always 0
unsigned int CurrentTexParameterFilter; // (GLuint) Used if UseTexParameterToSetSampler == true unsigned int CurrentTexParameterFilter; // (GLuint) Used if UseTexParameterFilter == true
}; };
IMGUI_IMPL_API ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState();
static inline ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState() { return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -5,6 +5,7 @@
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct. // [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLGPU3_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. // The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
@ -24,6 +25,7 @@
// CHANGELOG // CHANGELOG
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310) // 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262) // 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
@ -94,6 +96,11 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplSDLGPU3_RenderState* ImGui_ImplSDLGPU3_GetRenderState()
{
return (ImGui_ImplSDLGPU3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height) static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
{ {
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
@ -165,8 +172,8 @@ static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer*
void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer) void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0) if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0)
return; return;
@ -231,8 +238,8 @@ static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*,
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0) if (fb_width <= 0 || fb_height <= 0)
return; return;

View File

@ -5,6 +5,7 @@
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct. // [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLGPU3_GetRenderState().
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. // The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
@ -59,5 +60,6 @@ struct ImGui_ImplSDLGPU3_RenderState
{ {
SDL_GPUDevice* Device; SDL_GPUDevice* Device;
}; };
IMGUI_IMPL_API ImGui_ImplSDLGPU3_RenderState* ImGui_ImplSDLGPU3_GetRenderState();
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -56,7 +56,8 @@
#endif #endif
// SDL // SDL
#include <SDL.h> #include <SDL_render.h>
#include <SDL_version.h>
#if !SDL_VERSION_ATLEAST(2,0,17) #if !SDL_VERSION_ATLEAST(2,0,17)
#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function #error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
#endif #endif
@ -76,6 +77,11 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplSDLRenderer2_RenderState* ImGui_ImplSDLRenderer2_GetRenderState()
{
return (ImGui_ImplSDLRenderer2_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Functions // Functions
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer) static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
{ {

View File

@ -52,5 +52,6 @@ struct ImGui_ImplSDLRenderer2_RenderState
{ {
SDL_Renderer* Renderer; SDL_Renderer* Renderer;
}; };
IMGUI_IMPL_API ImGui_ImplSDLRenderer2_RenderState* ImGui_ImplSDLRenderer2_GetRenderState();
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -13,7 +13,7 @@
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLRenderer3_GetRenderState().
// Missing features: // Missing features:
// [ ] Renderer: Multi-viewport support (multiple windows). // [ ] Renderer: Multi-viewport support (multiple windows).
@ -27,6 +27,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)
// 2026-09-17: Restore modified texture scale modes at the end of RenderDrawData(). Added DrawCallback_SetSamplerFromTex support. Added CurrentScaleMode in ImGui_ImplSDLRenderer3_RenderState (#9543, #9378)
// 2026-07-15: Fixed default sampler state to be linear (broken 2026-04-23). (#9470, #9378) // 2026-07-15: Fixed default sampler state to be linear (broken 2026-04-23). (#9470, #9378)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295) // 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
@ -53,19 +54,24 @@
#endif #endif
// SDL // SDL
#include <SDL3/SDL.h> #include <SDL3/SDL_render.h>
#include <SDL3/SDL_version.h>
#if !SDL_VERSION_ATLEAST(3,0,0) #if !SDL_VERSION_ATLEAST(3,0,0)
#error This backend requires SDL 3.0.0+ #error This backend requires SDL 3.0.0+
#endif #endif
// SDL_Renderer data // SDL_Renderer data
struct ImGui_ImplSDLRenderer3_TexScaleModeEntry
{
SDL_Texture* Texture;
SDL_ScaleMode ScaleModeBackup;
};
struct ImGui_ImplSDLRenderer3_Data struct ImGui_ImplSDLRenderer3_Data
{ {
SDL_Renderer* Renderer; // Main viewport's renderer SDL_Renderer* Renderer; // Main viewport's renderer
ImVector<SDL_FColor> ColorBuffer; ImVector<SDL_FColor> ColorBuffer;
ImVector<ImGui_ImplSDLRenderer3_TexScaleModeEntry> TexScaleModeBackups; // Backup of texture scale modes
// Render State
SDL_ScaleMode CurrentScaleMode;
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); } ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
}; };
@ -77,17 +83,21 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplSDLRenderer3_RenderState* ImGui_ImplSDLRenderer3_GetRenderState()
{
return (ImGui_ImplSDLRenderer3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
// Functions // Functions
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer) static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
{ {
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState();
// Clear out any viewports and cliprect set by the user // Clear out any viewports and cliprect set by the user
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process. // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
SDL_SetRenderViewport(renderer, nullptr); SDL_SetRenderViewport(renderer, nullptr);
SDL_SetRenderClipRect(renderer, nullptr); SDL_SetRenderClipRect(renderer, nullptr);
render_state->CurrentScaleMode = SDL_SCALEMODE_LINEAR;
bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR;
} }
void ImGui_ImplSDLRenderer3_NewFrame() void ImGui_ImplSDLRenderer3_NewFrame()
@ -117,8 +127,61 @@ static int SDL_RenderGeometryRaw8BitColor(SDL_Renderer* renderer, ImVector<SDL_F
// Draw callbacks // Draw callbacks
static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way. static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR; } static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_NEAREST; } static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_INVALID; } // SDL_SCALEMODE_INVALID = use/keep value in texture.
// SDLRenderer has various design issues which makes it hard to do it compared to regular graphics API.
// - scale/filtering mode is tied to a texture.
// - scale/filtering mode is not queued as part of the SDL_RenderGeometryXXX commands, so a change in one texture requires a flush.
static void ImGui_ImplSDLRenderer3_TexScaleModeUpdate(SDL_Renderer* renderer, SDL_Texture* tex, SDL_ScaleMode desired_scale_mode)
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
if (desired_scale_mode != SDL_SCALEMODE_INVALID)
{
// Enforce a scale mode
SDL_ScaleMode tex_scale_mode = desired_scale_mode;
if (!SDL_GetTextureScaleMode(tex, &tex_scale_mode) || tex_scale_mode == desired_scale_mode)
return;
SDL_FlushRenderer(renderer);
SDL_SetTextureScaleMode(tex, desired_scale_mode);
// Store backup of old scale mode (FIXME-OPT)
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
if (entry.Texture == tex)
{
if (entry.ScaleModeBackup == SDL_SCALEMODE_INVALID)
entry.ScaleModeBackup = tex_scale_mode;
return;
}
ImGui_ImplSDLRenderer3_TexScaleModeEntry entry = { tex, tex_scale_mode };
bd->TexScaleModeBackups.push_back(entry);
}
else
{
// Use scale mode that was set in texture by user. If there is an entry, restore it and clear the entry.
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
if (entry.Texture == tex && entry.ScaleModeBackup != SDL_SCALEMODE_INVALID)
{
SDL_FlushRenderer(renderer);
SDL_SetTextureScaleMode(tex, entry.ScaleModeBackup);
entry.ScaleModeBackup = SDL_SCALEMODE_INVALID;
return;
}
}
}
static void ImGui_ImplSDLRenderer3_TexScaleModeRestoreBackups(SDL_Renderer* renderer)
{
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
if (bd->TexScaleModeBackups.Size == 0)
return;
SDL_FlushRenderer(renderer);
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
if (entry.ScaleModeBackup != SDL_SCALEMODE_INVALID)
SDL_SetTextureScaleMode(entry.Texture, entry.ScaleModeBackup);
bd->TexScaleModeBackups.resize(0);
}
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer) void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
{ {
@ -161,19 +224,19 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
SDL_GetRenderViewport(renderer, &old.Viewport); SDL_GetRenderViewport(renderer, &old.Viewport);
SDL_GetRenderClipRect(renderer, &old.ClipRect); SDL_GetRenderClipRect(renderer, &old.ClipRect);
// Setup desired state
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
// Setup render state structure (for callbacks and custom texture bindings) // Setup render state structure (for callbacks and custom texture bindings)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLRenderer3_RenderState render_state; ImGui_ImplSDLRenderer3_RenderState render_state;
render_state.Renderer = renderer; render_state.Renderer = renderer;
platform_io.Renderer_RenderState = &render_state; platform_io.Renderer_RenderState = &render_state;
// Setup desired state
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
IM_ASSERT(bd->TexScaleModeBackups.Size == 0);
// Will project scissor/clipping rectangles into framebuffer space // Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = render_scale; ImVec2 clip_scale = render_scale;
SDL_ScaleMode last_scale_mode = bd->CurrentScaleMode;
// Render command lists // Render command lists
for (const ImDrawList* draw_list : draw_data->CmdLists) for (const ImDrawList* draw_list : draw_data->CmdLists)
@ -203,20 +266,17 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; } if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue; continue;
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) }; SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
SDL_SetRenderClipRect(renderer, &r); SDL_SetRenderClipRect(renderer, &r);
// Setup texture scale/filtering mode
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
ImGui_ImplSDLRenderer3_TexScaleModeUpdate(renderer, tex, render_state.CurrentScaleMode);
// Draw
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos)); const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv)); const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+ const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col));
if (last_scale_mode != bd->CurrentScaleMode)
SDL_FlushRenderer(renderer);
// Bind texture, Draw
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex, SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex,
xy, (int)sizeof(ImDrawVert), xy, (int)sizeof(ImDrawVert),
color, (int)sizeof(ImDrawVert), color, (int)sizeof(ImDrawVert),
@ -231,6 +291,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
// Restore modified SDL_Renderer state // Restore modified SDL_Renderer state
SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr); SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr); SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
ImGui_ImplSDLRenderer3_TexScaleModeRestoreBackups(renderer);
} }
void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex) void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
@ -312,6 +373,7 @@ bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState; platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear; platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest; platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest;
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerFromTex;
bd->Renderer = renderer; bd->Renderer = renderer;

View File

@ -13,7 +13,7 @@
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLRenderer3_GetRenderState().
// Missing features: // Missing features:
// [ ] Renderer: Multi-viewport support (multiple windows). // [ ] Renderer: Multi-viewport support (multiple windows).
@ -29,7 +29,8 @@
#include "imgui.h" // IMGUI_IMPL_API #include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE #ifndef IMGUI_DISABLE
struct SDL_Renderer; // For SDL_ScaleMode which cannot be forward declared.
#include <SDL3/SDL_render.h>
// Follow "Getting Started" link and check examples/ folder to learn about using backends! // Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer); IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer);
@ -50,6 +51,8 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
struct ImGui_ImplSDLRenderer3_RenderState struct ImGui_ImplSDLRenderer3_RenderState
{ {
SDL_Renderer* Renderer; SDL_Renderer* Renderer;
SDL_ScaleMode CurrentScaleMode; // Current scale mode during render. Set to SDL_SCALEMODE_INVALID to use "SetSamplerFromTex" mode.
}; };
IMGUI_IMPL_API ImGui_ImplSDLRenderer3_RenderState* ImGui_ImplSDLRenderer3_GetRenderState();
#endif // #ifndef IMGUI_DISABLE #endif // #ifndef IMGUI_DISABLE

View File

@ -5,7 +5,7 @@
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions. // [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().
// [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport). // [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification. // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
@ -29,6 +29,8 @@
// 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)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-09-03: Added for support for multiple Vulkan contexts with custom loaders. (#6616)
// 2026-07-15: [Docking] Vulkan: fixed use-after-free when using multi-viewport with dynamic rendering path: deep-copy SurfaceFormat.format into the persistent buffer instead of storing a pointer to the viewport's wd->SurfaceFormat which dangles after the viewport is destroyed. (#9390, #9468) // 2026-07-15: [Docking] Vulkan: fixed use-after-free when using multi-viewport with dynamic rendering path: deep-copy SurfaceFormat.format into the persistent buffer instead of storing a pointer to the viewport's wd->SurfaceFormat which dangles after the viewport is destroyed. (#9390, #9468)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends. // 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.
@ -241,10 +243,28 @@ static bool g_FunctionsLoaded = true;
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkWaitForFences) IMGUI_VULKAN_FUNC_MAP_MACRO(vkWaitForFences)
struct ImGui_ImplVulkan_Functions
{
// Define function pointers // Define function pointers
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func; #define IMGUI_VULKAN_FUNC_DEF(func) PFN_##func pfn_##func;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF) IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
#undef IMGUI_VULKAN_FUNC_DEF #undef IMGUI_VULKAN_FUNC_DEF
};
// Globally available function pointers used for initialization of the backend data
static ImGui_ImplVulkan_Functions ImGuiImplVulkanFuncs;
// Multi Vulkan contexts support: wrap each Vulkan function pointer to properly dispatch it using the current backend data
static ImGui_ImplVulkan_Functions& ImGui_ImplVulkan_GetFunctions();
#define IMGUI_VULKAN_FUNC_WRAPPER(func) \
template<typename... Args> \
auto func(Args&&... args) -> decltype(ImGui_ImplVulkan_GetFunctions().pfn_##func(args...)) \
{ \
return ImGui_ImplVulkan_GetFunctions().pfn_##func(args...); \
}
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_WRAPPER)
#undef IMGUI_VULKAN_FUNC_WRAPPER
#endif // IMGUI_IMPL_VULKAN_USE_LOADER #endif // IMGUI_IMPL_VULKAN_USE_LOADER
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
@ -326,6 +346,11 @@ struct ImGui_ImplVulkan_Data
// Render buffers for main window // Render buffers for main window
ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers; ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers;
// Vulkan function pointers loaded for this context
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
ImGui_ImplVulkan_Functions Functions;
#endif
ImGui_ImplVulkan_Data() ImGui_ImplVulkan_Data()
{ {
memset((void*)this, 0, sizeof(*this)); memset((void*)this, 0, sizeof(*this));
@ -464,6 +489,21 @@ static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState()
{
return (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
// Get the Vulkan function pointers used by the current backend.
// If no backend is available, return the currently loaded global function pointers (ImGuiImplVulkanFuncs).
static ImGui_ImplVulkan_Functions& ImGui_ImplVulkan_GetFunctions()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
return bd ? bd->Functions : ImGuiImplVulkanFuncs;
}
#endif
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
{ {
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
@ -559,7 +599,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
constants[1] = 2.0f / draw_data->DisplaySize.y; constants[1] = 2.0f / draw_data->DisplaySize.y;
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1]; constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants); vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (uint32_t)sizeof(float) * 4, constants);
// Setup sampler // Setup sampler
vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);
@ -583,8 +623,8 @@ void ImGui_ImplVulkan_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImD
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline) void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
{ {
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0) if (fb_width <= 0 || fb_height <= 0)
return; return;
@ -1354,8 +1394,8 @@ bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER #ifdef IMGUI_IMPL_VULKAN_USE_LOADER
#define IMGUI_VULKAN_FUNC_LOAD(func) \ #define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \ ImGuiImplVulkanFuncs.pfn_##func = reinterpret_cast<PFN_##func>(loader_func(#func, user_data)); \
if (func == nullptr) \ if (ImGuiImplVulkanFuncs.pfn_##func == nullptr) \
return false; return false;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD) IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
#undef IMGUI_VULKAN_FUNC_LOAD #undef IMGUI_VULKAN_FUNC_LOAD
@ -1424,6 +1464,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE); IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE);
bd->VulkanInitInfo = *info; bd->VulkanInitInfo = *info;
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
bd->Functions = ImGuiImplVulkanFuncs;
#endif
VkPhysicalDeviceProperties properties; VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties); vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties);

View File

@ -5,7 +5,7 @@
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions. // [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().
// [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport). // [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification. // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
@ -183,6 +183,7 @@ struct ImGui_ImplVulkan_RenderState
VkPipeline Pipeline; VkPipeline Pipeline;
VkPipelineLayout PipelineLayout; VkPipelineLayout PipelineLayout;
}; };
IMGUI_IMPL_API ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers // Internal / Miscellaneous Vulkan Helpers

View File

@ -5,8 +5,8 @@
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplWGPU_GetRenderState().
// Missing features or Issues: // Missing features or Issues:
// [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop. // [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop.
@ -22,6 +22,8 @@
// 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)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-31: Update to compile with wgpu-native 29.0. (#9377, #9532, #9530)
// 2026-08-18: Fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport() when FramebufferScale is >1.0f. (#9515, #8628) // 2026-08-18: Fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport() when FramebufferScale is >1.0f. (#9515, #8628)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257) // 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
@ -68,12 +70,6 @@
#error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore. #error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore.
#endif #endif
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
// Using type alias until WGPU adopts the same naming convention (#8369)
using WGPUProgrammableStageDescriptor = WGPUComputeState;
#endif
// Dear ImGui prototypes from imgui_internal.h // Dear ImGui prototypes from imgui_internal.h
extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed); extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed);
#define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro). #define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro).
@ -135,6 +131,11 @@ static ImGui_ImplWGPU_Data* ImGui_ImplWGPU_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplWGPU_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; return ImGui::GetCurrentContext() ? (ImGui_ImplWGPU_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
} }
ImGui_ImplWGPU_RenderState* ImGui_ImplWGPU_GetRenderState()
{
return (ImGui_ImplWGPU_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// SHADERS // SHADERS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -319,7 +320,7 @@ static void SafeRelease(FrameResources& res)
SafeRelease(res.VertexBufferHost); SafeRelease(res.VertexBufferHost);
} }
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source) static WGPUComputeState ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
{ {
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
IM_UNUSED(bd); IM_UNUSED(bd);
@ -346,7 +347,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(con
pop_cb.userdata1 = &validation_error; pop_cb.userdata1 = &validation_error;
wgpuDevicePopErrorScope(bd->wgpuDevice, pop_cb); wgpuDevicePopErrorScope(bd->wgpuDevice, pop_cb);
WGPUProgrammableStageDescriptor stage_desc = {}; WGPUComputeState stage_desc = {};
if (module && !validation_error) if (module && !validation_error)
{ {
stage_desc.module = module; stage_desc.module = module;
@ -359,7 +360,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(con
return stage_desc; return stage_desc;
} }
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length) static WGPUComputeState ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
{ {
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
@ -371,7 +372,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(co
WGPUShaderModuleDescriptor desc = {}; WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = (WGPUChainedStruct*)&spirv_desc; desc.nextInChain = (WGPUChainedStruct*)&spirv_desc;
WGPUProgrammableStageDescriptor stage_desc = {}; WGPUComputeState stage_desc = {};
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc); stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
stage_desc.entryPoint = { "main", WGPU_STRLEN }; stage_desc.entryPoint = { "main", WGPU_STRLEN };
@ -443,9 +444,9 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
} }
// Setup viewport // Setup viewport
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, fb_width, fb_height, 0, 1); wgpuRenderPassEncoderSetViewport(ctx, 0, 0, (float)fb_width, (float)fb_height, 0, 1);
// Bind shader and vertex buffers // Bind shader and vertex buffers
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert)); wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert));
@ -467,8 +468,8 @@ static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, con
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder) void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{ {
// Avoid rendering when minimized // Avoid rendering when minimized
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0) if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return; return;
@ -774,7 +775,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc); graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
// Create the vertex shader // Create the vertex shader
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl); WGPUComputeState vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv)); if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv));
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module; graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint; graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
@ -782,15 +783,9 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
// Vertex input configuration // Vertex input configuration
WGPUVertexAttribute attribute_desc[] = WGPUVertexAttribute attribute_desc[] =
{ {
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 }, { nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 }, { nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 }, { nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
#else
{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
{ WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
#endif
}; };
WGPUVertexBufferLayout buffer_layouts[1]; WGPUVertexBufferLayout buffer_layouts[1];
@ -803,7 +798,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
graphics_pipeline_desc.vertex.buffers = buffer_layouts; graphics_pipeline_desc.vertex.buffers = buffer_layouts;
// Create the pixel shader // Create the pixel shader
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl); WGPUComputeState pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv)); if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv));
// Create the blending setup // Create the blending setup
@ -996,11 +991,7 @@ void ImGui_ImplWGPU_NewFrame()
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status) bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
{ {
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
return (status == WGPUSurfaceGetCurrentTextureStatus_Error); return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
#else
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
#endif
} }
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status) bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status)
@ -1013,7 +1004,6 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus
} }
// Helpers to obtain a string // Helpers to obtain a string
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type) const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
{ {
switch (type) switch (type)
@ -1036,7 +1026,7 @@ const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type)
default: return "Unknown"; default: return "Unknown";
} }
} }
#elif !defined(__EMSCRIPTEN__) #if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level) const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level)
{ {
switch (level) switch (level)

View File

@ -17,8 +17,8 @@
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef! // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures). // [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplWGPU_GetRenderState().
// Missing features or Issues: // Missing features or Issues:
// [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop. // [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop.
@ -83,6 +83,7 @@ struct ImGui_ImplWGPU_RenderState
WGPUDevice Device; WGPUDevice Device;
WGPURenderPassEncoder RenderPassEncoder; WGPURenderPassEncoder RenderPassEncoder;
}; };
IMGUI_IMPL_API ImGui_ImplWGPU_RenderState* ImGui_ImplWGPU_GetRenderState();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Internal Helpers // Internal Helpers
@ -97,10 +98,9 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextur
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter); void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type); const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type); const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type); const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type); const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) #if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level); const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
#endif #endif

View File

@ -72,7 +72,7 @@ For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree
In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder: In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder:
List of Platforms Backends: List of Platform Backends:
imgui_impl_android.cpp ; Android native app API imgui_impl_android.cpp ; Android native app API
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/ imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/

View File

@ -42,9 +42,11 @@ HOW TO UPDATE?
Breaking Changes: Breaking Changes:
- Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in
favor of `style.CurveTesselationMaxError` (default 1.12)` which is in Pixels unit. It is favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit. It is
easier to tweak + this allows us to easily scale error threshold on high density screens. easier to tweak + this allows us to easily scale error threshold on high density screens.
- style.CurveTesselationMaxError == sqrf(style.CurveTessellationTol). - style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
- ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`:
prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
- Backends: - Backends:
- DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was - DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was
obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support
@ -52,28 +54,109 @@ Breaking Changes:
Other Changes: Other Changes:
- Drags, Sliders:
- Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
- Ongoing drags may be cancelled using Right-Click, Escape or Gamepad Triangle.
Cancelling reverts to the initial value. (#8564, #9534)
- TreeNode:
- Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
features or other features requiring stack storage. (#9509) [@lasrod]
- TabBar:
- Improved scroll target when clicking a Tab that is larger than the scrolling
section width.
- Using <> scrolling buttons while the selected Tab is at either end of the
section mid-section but not fully visible always makes it fully visible
(before eventually selecting a Tab in the leading/trailing section)
- Selectable:
- Fixed `ImGuiSelectableFlags_SelectOnNav` triggering during NavInit.
- Fonts: - Fonts:
- Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic - Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic
to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of
ProggyClean on most Apple/Retina setups by default. ProggyClean on most Apple/Retina setups by default.
- ImDrawList: - ColorEdit:
- ColorButton, ColorEdit, ColorPicker: cancel-out alpha caused by BeginDisabled() so
disabled color buttons have the same color as non-disabled oness. (#9511)
- ColorButton: fixed issues/inconsistencies with checkerboard rendering when combining
color alpha and global style alpha. (#9511) [@enjmiah, @ocornut]
- Popups:
- Amended context menu right-click opening code to check that the right-click
hasn't been owned by another items. This is more correct and also necessary
to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
- ImGuiTextFilter:
- Added support for space as an "and" filter, which is the standard. (#2435, #30)
e.g. w/ filter 'hello world' (without quotes) both words needs to be in input data.
- Added support for double-quoted "xxx" blocks to e.g. match words sequences. (#2435)
e.g. w/ filter "hello world" the exact sequence needs to be in input data.
- Fixed filtering when mixing "include" and "-exclude" keyword so that an "-exclude"
match always filters out. (#2435) [@kudaba, @ocornut]
- Added `DrawWithHint()` function. (#6206, #6395, #6447)
- Added a "incl -excl" hint by default when the search field is empty. (#6206, #6395, #6447)
- Style:
- Inverted `ImGuiCol_TitleBgXXX` colors for `StyleColorsLight()` so that the selected
window title bar appears brighter.
- Misc:
- Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values.
Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX()
and Combo() functions.
The scoped flag is designed for usage by advanced property editors. (#5518, #5677, #6865)
- Fixed `GetBackgroundDrawList()`/`GetForegroundDrawList()` not being properly reset
every frame when cumulated session time is very large (e.g. a few days). [@lailoken]
- Added `IM_NODEBUGSTEP` helper to tag functions with `__declspec(non_user_code)` (MSVC)
or `[[gnu::artificial]]` (Clang/GCC) in order to provide a hint to debuggers to skip
trivial functions when stepping into.
- Tagged various trivial functions using `IM_NODEBUGSTEP`: `ImVec2()`, `ImVec4()` etc.
and various operators.
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing
issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
- DrawList:
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists: - Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
- AA Fringe is scaled accordingly. - AA Fringe is scaled accordingly.
- Circle and Curves tessellation error are scaled accordingly. - Circle and Curves tessellation error are scaled accordingly.
- Reworked assert in PushTexture() to allow convenience grace period of using a
texture that was queue for destroy during the frame. Make it safe to stick to
an existing texture during the frame. (#9528, #8465)
- Added optional `platform_io.DrawCallback_SetSamplerFromTex` standard backend-agnostic
draw callback for requesting to use the sampler associated already associated to a texture.
Currently only supported by the OpenGL2/3 and SDLRenderer3 backend. (#9378)
- Demo:
- Added `Widgets->Mixed Values` section. (#5518, #5677, #6865)
- Style Editor: fixed style/colors combo box applying style when opening Combo.
- Backends: - Backends:
- QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry] - QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry]
- OpenGL2, OpenGL3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw
callback to request using the sampler associated already associated to a texture. (#9378)
- OpenGL2, OpenGL3: fixed `DrawCallback_ResetRenderState` handler not reseting all states
in the glTexParameter() path. (#9378)
- SDL2: fixed querying framebuffer scale/density when using Metal without - SDL2: fixed querying framebuffer scale/density when using Metal without
going through a SDL_Renderer. (#5592) [@lailoken] going through a SDL_Renderer. (#5592) [@lailoken]
- SDLRenderer3: restore any temporarily modified texture scale modes at the of `RenderDrawData()`. (#9378)
- SDLRenderer3: expose CurrentScaleMode in ImGui_ImplSDLRenderer3_RenderState. (#9543, #9378) [@Clownacy]
- SDLRenderer3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw callback to request
using the sampler associated already associated to a texture via `SDL_SetTextureScaleMode()`. (#9378)
It is equivalent to setting `render_state->CurrentScaleMode = SDL_SCALEMODE_INVALID`.
Note: this callback is only supported by selected rendering backends: most other graphics API
don't have the equivalent of `SDL_SetTextureScaleMode()` and the callback won't work with them.
- Vulkan: added for support for multiple Vulkan contexts with custom loaders. (#6616) [@lstalmir]
- WebGPU: fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport()` - WebGPU: fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport()`
when when `FramebufferScale` is >1.0f. (#9515, #8628) [@WayU] when when `FramebufferScale` is >1.0f. (#9515, #8628) [@WayU]
- WebGPU: update to build with wgpu-native 29.0+. (#9377, #9532, #9530) [@lucascompython, @ivan-enzhaev]
- Examples: - Examples:
- SDL2+Metal: create Metal context without using a SDL_Renderer. - MSVC: disabled /JMC in Visual Studio projects (unnecessary overhead).
- GLFW/SDL2/SDL3+WebGPU: fixed running with wgpu-native missing `wgpuInstanceWaitAny()`. (#9377)
- SDL2+Metal: create Metal context without using a `SDL_Renderer`.
- QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry] - QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry]
- OSX+OpenGL3: added example_apple_opengl3/ (OSX/Cocoa + OpenGL 3.2 Core profile). - OSX+OpenGL3: added example_apple_opengl3/ (OSX/Cocoa + OpenGL 3.2 Core profile).
Docking+Viewports Branch: Docking+Viewports Branch:
- Style:
- Changed `ImGuiCol_DockingEmptyBg` value for `StyleColorsLight()`.
- Backends: - Backends:
- DX10, DX11, DX12: fixed crash when CreateSwapChain() or CreateRenderTargetView()
calls are failing. (#9546)
- GLFW: fixed applying mouse cursor shapes to secondary viewports, broken in 1.92.6
when introducing a cache. (#9545) [@JamesWrigley]
- Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856) [@laikoken] - Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856) [@laikoken]
- Examples: - Examples:
- SDL3+Metal, GLFW+Metal: fix multi-viewport support. - SDL3+Metal, GLFW+Metal: fix multi-viewport support.

View File

@ -3,7 +3,7 @@
## Index ## Index
- [Getting Started & General Advice](#getting-started--general-advice) - [Getting Started & General Advice](#getting-started--general-advice)
- [Issues vs Discussions](#issues-vs-discussions) - [Using "Issues" for almost everything!](using-issues-for-almost-everything)
- [How to open an Issue](#how-to-open-an-issue) - [How to open an Issue](#how-to-open-an-issue)
- [How to open a Pull Request](#how-to-open-a-pull-request) - [How to open a Pull Request](#how-to-open-a-pull-request)
- [Copyright / Contributor License Agreement](#copyright--contributor-license-agreement) - [Copyright / Contributor License Agreement](#copyright--contributor-license-agreement)
@ -23,18 +23,20 @@
- If you get a crash or assert, use a debugger to locate the line triggering it and read the comments around. - If you get a crash or assert, use a debugger to locate the line triggering it and read the comments around.
- Please don't be a [Help Vampire](https://slash7.com/2006/12/22/vampires/). - Please don't be a [Help Vampire](https://slash7.com/2006/12/22/vampires/).
## 'Issues' vs 'Discussions' ## Using "Issues" for almost everything!
We are happy to use 'Issues' for many type of open-ended questions. We are encouraging 'Issues' becoming an enormous, centralized and cross-referenced database of Dear ImGui contents. We are happy to use 'Issues' for many type of open-ended questions.
We are encouraging 'Issues' becoming an enormous, centralized and cross-referenced database of Dear ImGui contents.
Only if you: - Need help using the API? Open an Issue!
- Want to suggest a feature? Open an Issue!
- etc.
ONLY IN THOSE CASE you can use the [Discussions forums](https://github.com/ocornut/imgui/discussions)
- Cannot BUILD or LINK examples. - Cannot BUILD or LINK examples.
- Cannot BUILD, or LINK, or RUN Dear ImGui in your application or custom engine. - Cannot BUILD, or LINK, or RUN Dear ImGui in your application or custom engine.
- Cannot LOAD a font.
Then please [use the Discussions forums](https://github.com/ocornut/imgui/discussions) instead of opening an issue. If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new Issue.
If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new issue.
## How to open an issue ## How to open an issue

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -143,8 +143,8 @@
ImDrawData* draw_data = ImGui::GetDrawData(); ImDrawData* draw_data = ImGui::GetDrawData();
[[self openGLContext] makeCurrentContext]; [[self openGLContext] makeCurrentContext];
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);

View File

@ -143,8 +143,8 @@
ImDrawData* draw_data = ImGui::GetDrawData(); ImDrawData* draw_data = ImGui::GetDrawData();
[[self openGLContext] makeCurrentContext]; [[self openGLContext] makeCurrentContext];
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,6 +110,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -1,10 +1,3 @@
# Building for desktop with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for desktop with WGPU-Native: # Building for desktop with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases # 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder # 2. unzip the downloaded file in your_preferred_folder
@ -13,7 +6,14 @@
# The resulting binary will be found at one of the following locations: # The resulting binary will be found at one of the following locations:
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe] # * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for desktop with WGVK (MUCH EASIER) # Building for desktop with Dawn: (VERY LONG TO BUILD)
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
# Building for desktop with WGVK:
# 1. git clone https://github.com/manuel5975p/WGVK wgvk # 1. git clone https://github.com/manuel5975p/WGVK wgvk
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
# 3. cmake --build build # 3. cmake --build build
@ -29,7 +29,7 @@
# 4. emrun build/index.html # 4. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22 cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_glfw_wgpu C CXX) project(example_glfw_wgpu C CXX)
set(IMGUI_EXECUTABLE example_glfw_wgpu) set(IMGUI_EXECUTABLE example_glfw_wgpu)

View File

@ -345,29 +345,25 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success) if (status != WGPURequestAdapterStatus_Success)
{ {
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
}
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1; WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter; *extAdapter = adapter;
}
else
{
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
} }
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success) if (status != WGPURequestDeviceStatus_Success)
{ {
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
}
WGPUDevice* extDevice = (WGPUDevice*)userdata1; WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device; *extDevice = device;
}
else
{
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
}
} }
static WGPUAdapter RequestAdapter(WGPUInstance& instance) static WGPUAdapter RequestAdapter(WGPUInstance& instance)
@ -381,8 +377,10 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
adapterCallbackInfo.userdata1 = &local_adapter; adapterCallbackInfo.userdata1 = &local_adapter;
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo); WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#endif
IM_ASSERT(local_adapter && "Error on Adapter request"); IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter; return local_adapter;
} }
@ -394,15 +392,20 @@ static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly; deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
deviceCallbackInfo.callback = handle_request_device; deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device; deviceCallbackInfo.userdata1 = &local_device;
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo); WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#else
IM_UNUSED(instance);
#endif
IM_ASSERT(local_device && "Error on Device request"); IM_ASSERT(local_device && "Error on Device request");
return local_device; return local_device;
} }
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU #endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
bool InitWGPU(GLFWwindow* window) static bool InitWGPU(GLFWwindow* window)
{ {
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
@ -451,7 +454,7 @@ bool InitWGPU(GLFWwindow* window)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) #if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback( wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr [](WGPULogLevel level, WGPUStringView msg, void*) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
); );
wgpuSetLogLevel(WGPULogLevel_Warn); wgpuSetLogLevel(WGPULogLevel_Warn);
#endif #endif

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -88,6 +88,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -102,6 +103,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -108,6 +109,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -108,6 +109,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,6 +110,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -1,10 +1,3 @@
# Building for desktop with Dawn:
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for desktop with WGPU-Native: # Building for desktop with WGPU-Native:
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases # 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
# 2. unzip the downloaded file in your_preferred_folder # 2. unzip the downloaded file in your_preferred_folder
@ -13,7 +6,14 @@
# The resulting binary will be found at one of the following locations: # The resulting binary will be found at one of the following locations:
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe] # * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for desktop with WGVK (MUCH EASIER) # Building for desktop with Dawn: (VERY LONG TO BUILD)
# 1. git clone https://github.com/google/dawn dawn
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
# 3. cmake --build build
# The resulting binary will be found at one of the following locations:
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
# Building for desktop with WGVK:
# 1. git clone https://github.com/manuel5975p/WGVK wgvk # 1. git clone https://github.com/manuel5975p/WGVK wgvk
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
# 3. cmake --build build # 3. cmake --build build
@ -29,7 +29,7 @@
# 4. emrun build/index.html # 4. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22 cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl2_wgpu C CXX) project(example_sdl2_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl2_wgpu) set(IMGUI_EXECUTABLE example_sdl2_wgpu)
@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif() endif()
set(CMAKE_CXX_STANDARD 10) # Dawn requires C++20 set(CMAKE_CXX_STANDARD 20) # Dawn requires C++20
# Dear ImGui # Dear ImGui
set(IMGUI_DIR ../../) set(IMGUI_DIR ../../)

View File

@ -330,29 +330,25 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success) if (status != WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{ {
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data); printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
} }
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
} }
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success) if (status != WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{ {
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data); printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
} }
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
} }
static WGPUAdapter RequestAdapter(WGPUInstance& instance) static WGPUAdapter RequestAdapter(WGPUInstance& instance)
@ -366,8 +362,10 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
adapterCallbackInfo.userdata1 = &local_adapter; adapterCallbackInfo.userdata1 = &local_adapter;
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo); WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#endif
IM_ASSERT(local_adapter && "Error on Adapter request"); IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter; return local_adapter;
} }
@ -379,9 +377,14 @@ static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly; deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
deviceCallbackInfo.callback = handle_request_device; deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device; deviceCallbackInfo.userdata1 = &local_device;
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo); WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#else
IM_UNUSED(instance);
#endif
IM_ASSERT(local_device && "Error on Device request"); IM_ASSERT(local_device && "Error on Device request");
return local_device; return local_device;
} }
@ -437,7 +440,7 @@ static bool InitWGPU(SDL_Window* window)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) #if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback( wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr [](WGPULogLevel level, WGPUStringView msg, void*) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
); );
wgpuSetLogLevel(WGPULogLevel_Warn); wgpuSetLogLevel(WGPULogLevel_Warn);
#endif #endif

View File

@ -93,6 +93,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -108,6 +109,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,6 +110,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -92,6 +92,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -107,6 +108,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -93,6 +93,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,6 +110,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -29,7 +29,7 @@
# 5. emrun build/index.html # 5. emrun build/index.html
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22 cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
project(imgui_example_sdl3_wgpu C CXX) project(example_sdl3_wgpu C CXX)
set(IMGUI_EXECUTABLE example_sdl3_wgpu) set(IMGUI_EXECUTABLE example_sdl3_wgpu)

View File

@ -341,29 +341,25 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestAdapterStatus_Success) if (status != WGPURequestAdapterStatus_Success)
{
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
}
else
{ {
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data); printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
} }
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
*extAdapter = adapter;
} }
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2) static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
{ {
IM_UNUSED(userdata2); IM_UNUSED(userdata2);
if (status == WGPURequestDeviceStatus_Success) if (status != WGPURequestDeviceStatus_Success)
{
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
}
else
{ {
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data); printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
return;
} }
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
*extDevice = device;
} }
static WGPUAdapter RequestAdapter(WGPUInstance& instance) static WGPUAdapter RequestAdapter(WGPUInstance& instance)
@ -377,8 +373,10 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
adapterCallbackInfo.userdata1 = &local_adapter; adapterCallbackInfo.userdata1 = &local_adapter;
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo); WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#endif
IM_ASSERT(local_adapter && "Error on Adapter request"); IM_ASSERT(local_adapter && "Error on Adapter request");
return local_adapter; return local_adapter;
} }
@ -390,9 +388,14 @@ static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly; deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
deviceCallbackInfo.callback = handle_request_device; deviceCallbackInfo.callback = handle_request_device;
deviceCallbackInfo.userdata1 = &local_device; deviceCallbackInfo.userdata1 = &local_device;
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo); WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
WGPUFutureWaitInfo waitInfo = { future, false }; WGPUFutureWaitInfo waitInfo = { future, false };
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull); wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
#else
IM_UNUSED(instance);
#endif
IM_ASSERT(local_device && "Error on Device request"); IM_ASSERT(local_device && "Error on Device request");
return local_device; return local_device;
} }
@ -448,7 +451,7 @@ static bool InitWGPU(SDL_Window* window)
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) #if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
wgpuSetLogCallback( wgpuSetLogCallback(
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr [](WGPULogLevel level, WGPUStringView msg, void*) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
); );
wgpuSetLogLevel(WGPULogLevel_Warn); wgpuSetLogLevel(WGPULogLevel_Warn);
#endif #endif

View File

@ -88,6 +88,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -102,6 +103,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -88,6 +88,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -102,6 +103,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -89,6 +89,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -104,6 +105,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -88,6 +88,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -102,6 +103,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -88,6 +88,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -102,6 +103,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..;..\..\backends;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -89,6 +89,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -104,6 +105,7 @@
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -107,15 +107,18 @@
// This will be inlined as part of ImVec2 and ImVec4 class declarations. // This will be inlined as part of ImVec2 and ImVec4 class declarations.
/* /*
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ IM_NODEBUGSTEP constexpr inline ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); } IM_NODEBUGSTEP inline operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \ #define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ IM_NODEBUGSTEP constexpr inline ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); } IM_NODEBUGSTEP inline operator MyVec4() const { return MyVec4(x,y,z,w); }
*/ */
//---- ...Or use Dear ImGui's own very basic math operators. //---- ...Or use Dear ImGui's own basic math operators in every file including imgui.h:
//#ifndef IMGUI_DEFINE_MATH_OPERATORS
//#define IMGUI_DEFINE_MATH_OPERATORS //#define IMGUI_DEFINE_MATH_OPERATORS
//#endif
//---- ...Or manually '#define IMGUI_DEFINE_MATH_OPERATORS' before '#include "imgui.h"' to use from one file.
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).

223
imgui.cpp
View File

@ -402,8 +402,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos) you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
- likewise io.MousePos and GetMousePos() will use OS coordinates. - 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. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTesselationMaxError` (default 1.12)` which is in Pixels unit.
- style.CurveTesselationMaxError == sqrf(style.CurveTessellationTol). - 2026/09/18 (1.93.0) - ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`: prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit.
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
- 2026/07/20 (1.92.9) - DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now defaulting to being disabled: - 2026/07/20 (1.92.9) - DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now defaulting to being disabled:
inputting a value with the keyboard doesn't write intermediate values to backing variable. (#9476) inputting a value with the keyboard doesn't write intermediate values to backing variable. (#9476)
- Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123. - Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123.
@ -1404,10 +1406,9 @@ static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf); static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
// Platform Dependents default implementation for ImGuiPlatformIO functions // Platform Dependents default implementation for ImGuiPlatformIO functions
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io);
static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx); static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx);
static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text); static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text);
static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data);
static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path);
namespace ImGui namespace ImGui
{ {
@ -1603,7 +1604,7 @@ ImGuiStyle::ImGuiStyle()
DockingSeparatorSize = 2.0f; // Thickness of resizing border between docked windows DockingSeparatorSize = 2.0f; // Thickness of resizing border between docked windows
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
// Rendering & Tesselation // Rendering & Tessellation
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.). AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
@ -3155,11 +3156,11 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
// [SECTION] ImGuiTextFilter // [SECTION] ImGuiTextFilter
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" // Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'.
ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
{ {
InputBuf[0] = 0; InputBuf[0] = 0;
CountGrep = 0; _CountExclude = 0;
if (default_filter) if (default_filter)
{ {
ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf)); ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf));
@ -3167,84 +3168,110 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
} }
} }
bool ImGuiTextFilter::Draw(const char* label, float width) bool ImGuiTextFilter::Draw(const char* label)
{ {
if (width != 0.0f) return DrawWithHint(label, "incl -excl");
ImGui::SetNextItemWidth(width); }
bool value_changed = ImGui::InputText(label, InputBuf, IM_COUNTOF(InputBuf));
// Use ImGui::SetNextItemWidth() manually if you want to use this.
bool ImGuiTextFilter::DrawWithHint(const char* label, const char* hint)
{
bool value_changed = ImGui::InputTextWithHint(label, hint, InputBuf, IM_COUNTOF(InputBuf));
if (value_changed) if (value_changed)
Build(); Build();
return value_changed; return value_changed;
} }
void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRange>* out) const // Parse filter and split into a format optimal for PassFilter()
{
out->resize(0);
const char* wb = b;
const char* we = wb;
while (we < e)
{
if (*we == separator)
{
out->push_back(ImGuiTextRange(wb, we));
wb = we + 1;
}
we++;
}
if (wb != we)
out->push_back(ImGuiTextRange(wb, we));
}
void ImGuiTextFilter::Build() void ImGuiTextFilter::Build()
{ {
Filters.resize(0); _Items.resize(0);
ImGuiTextRange input_range(InputBuf, InputBuf + ImStrlen(InputBuf)); _CountExclude = 0;
input_range.split(',', &Filters);
CountGrep = 0; const char* buf_e = InputBuf + ImStrlen(InputBuf);
for (ImGuiTextRange& f : Filters) const char* word_e;
int seq_incl_start_idx = -1;
for (const char* word_b = InputBuf; word_b < buf_e; word_b = word_e + 1)
{ {
while (f.b < f.e && ImCharIsBlankA(f.b[0])) // Trim blanks
f.b++; while (word_b < buf_e && ImCharIsBlankA(word_b[0])) // FIXME: UTF-8 support
while (f.e > f.b && ImCharIsBlankA(f.e[-1])) word_b++;
f.e--; const bool is_excl = (word_b < buf_e && word_b[0] == '-');
if (f.empty()) if (is_excl)
continue; word_b++;
if (f.b[0] != '-') const bool is_quote = (word_b < buf_e && word_b[0] == '\"');
CountGrep += 1; if (is_quote)
}
}
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
{
if (Filters.Size == 0)
return true;
if (text == NULL)
text = text_end = "";
for (const ImGuiTextRange& f : Filters)
{ {
if (f.b == f.e) // Parsing quotes. Omit storing leading/trailing quotes.
continue; word_e = ImStrchrRange(++word_b, buf_e, '\"');
if (f.b[0] == '-') if (word_e == NULL)
{ word_e = buf_e;
// Subtract
if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
return false;
} }
else else
{ {
// Grep // Handle both ' ' and ',' separators.
if (ImStristr(text, text_end, f.b, f.e) != NULL) for (word_e = word_b; word_e < buf_e; word_e++)
return true; if (*word_e == ' ' || *word_e == ',')
break;
}
// Min length
if (word_e - word_b > 0)
{
// Add to list. The '-' is not stored in items but implicitly inferred using (n < CountExclude).
// FIXME-OPT: as items are derived from user input buffer and we expect the insert() to behave sanely.
if (is_excl)
{
_Items.insert(_Items.Data + _CountExclude, ImGuiTextFilterItem(word_b, word_e));
_CountExclude++;
if (seq_incl_start_idx != -1)
seq_incl_start_idx++;
}
else
{
if (seq_incl_start_idx == -1)
seq_incl_start_idx = _Items.Size;
_Items.insert(_Items.Data + _Items.Size, ImGuiTextFilterItem(word_b, word_e));
_Items.Data[seq_incl_start_idx].CountInclude++;
} }
} }
// Implicit * grep // Next sequence
if (CountGrep == 0) if (word_e[0] == ',')
return true; seq_incl_start_idx = -1;
}
}
// FIXME: Could use a specialized ImStristr() + pre-convert our filter to uppercase.
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
{
if (_Items.Size == 0)
return true;
if (text == NULL)
text = text_end = "";
// Filters are sorted so that '-' ones are always leading.
ImGuiTextFilterItem* seq = _Items.Data;
ImGuiTextFilterItem* seq_excl_end = _Items.Data + _CountExclude;
for (; seq < seq_excl_end; seq++)
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) != NULL)
return false;
// Process includes
ImGuiTextFilterItem* seq_incl_end = _Items.Data + _Items.Size;
if (seq == seq_incl_end) // When no inclusion are specified (only exclusions) we implicitly pass
return true;
while (seq < seq_incl_end)
{
ImGuiTextFilterItem* seq_next = seq + seq->CountInclude;
IM_ASSERT_PARANOID(seq->CountInclude > 0 && seq_next <= seq_incl_end);
for (; seq < seq_next; seq++)
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) == NULL)
break;
if (seq == seq_next) // All matched
return true;
seq = seq_next; // Try next
}
return false; return false;
} }
@ -4019,6 +4046,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
// Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take // Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take
// better advantage of the render function taking size into account for coarse clipping. // better advantage of the render function taking size into account for coarse clipping.
void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
// DOES NOT CALL LogRenderedText(), unlike RenderTextClipped!!!
{ {
// Perform CPU side clipping for single clipped element to avoid using scissor state // Perform CPU side clipping for single clipped element to avoid using scissor state
ImVec2 pos = pos_min; ImVec2 pos = pos_min;
@ -4420,7 +4448,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0; NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
NavJustMovedToKeyMods = ImGuiMod_None; NavJustMovedToKeyMods = ImGuiMod_None;
NavJustMovedToIsTabbing = false; NavJustMovedToIsTabbing = NavJustMovedToIsInit = false;
NavJustMovedToHasSelectionData = false; NavJustMovedToHasSelectionData = false;
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac... // All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
@ -4464,6 +4492,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
MouseCursor = ImGuiMouseCursor_Arrow; MouseCursor = ImGuiMouseCursor_Arrow;
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
MixedValueLabel = "-";
InputTextPasswordFontBackupFlags = ImFontFlags_None; InputTextPasswordFontBackupFlags = ImFontFlags_None;
InputTextReactivateId = 0; InputTextReactivateId = 0;
TempInputId = 0; TempInputId = 0;
@ -4572,10 +4601,7 @@ void ImGui::Initialize()
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_COUNTOF(GLocalizationEntriesEnUS)); LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_COUNTOF(GLocalizationEntriesEnUS));
// Setup default ImGuiPlatformIO clipboard/IME handlers. // Setup default ImGuiPlatformIO clipboard/IME handlers.
g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations InitializeDefaultPlatformHandlers(g.PlatformIO);
g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
// Setup session starting date // Setup session starting date
#ifndef IMGUI_DISABLE_TIME_FUNCTIONS #ifndef IMGUI_DISABLE_TIME_FUNCTIONS
@ -5424,12 +5450,13 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
} }
// Our ImDrawList system requires that there is always a command // Our ImDrawList system requires that there is always a command
if (viewport->BgFgDrawListsLastTimeActive[drawlist_no] != (float)g.Time) if (viewport->BgFgDrawListsLastFrameActive[drawlist_no] != g.FrameCount)
{ {
draw_list->_ResetForNewFrame(); draw_list->_ResetForNewFrame();
draw_list->_SetPixelDensity(viewport->FramebufferScale.x); draw_list->_SetPixelDensity(viewport->FramebufferScale.x);
draw_list->PushTexture(g.IO.Fonts->TexRef); draw_list->PushTexture(g.IO.Fonts->TexRef);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false); draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->BgFgDrawListsLastFrameActive[drawlist_no] = g.FrameCount;
viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time; viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time;
} }
return draw_list; return draw_list;
@ -6466,7 +6493,7 @@ void ImGui::Render()
for (ImGuiViewportP* viewport : g.Viewports) for (ImGuiViewportP* viewport : g.Viewports)
{ {
InitViewportDrawData(viewport); InitViewportDrawData(viewport);
if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastTimeActive[0] == (float)g.Time) if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastFrameActive[0] == g.FrameCount)
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport)); AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
} }
@ -6498,7 +6525,7 @@ void ImGui::Render()
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder); FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
// Add foreground ImDrawList (for each active viewport) // Add foreground ImDrawList (for each active viewport)
if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastTimeActive[1] == (float)g.Time) if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastFrameActive[1] == g.FrameCount)
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport)); AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch). // We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
@ -13474,7 +13501,7 @@ bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (IsMouseReleased(mouse_button, id) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
return true; return true;
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId)) if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
return true; return true;
@ -13485,7 +13512,7 @@ bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (IsMouseReleased(mouse_button, ImGuiKeyOwner_NoOwner) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered()) if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
return true; return true;
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID) if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
@ -13556,9 +13583,9 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flag
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!str_id) if (!str_id)
str_id = "void_context"; str_id = "void_context";
ImGuiID id = window->GetID(str_id); ImGuiID id = window->GetID(str_id); // FIXME: Use a global ID?
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags); ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow)) if (IsMouseReleased(mouse_button, id) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
if (GetTopMostPopupModal() == NULL) if (GetTopMostPopupModal() == NULL)
OpenPopupEx(id, popup_flags); OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
@ -14886,6 +14913,7 @@ void ImGui::NavInitRequestApplyResult()
g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = 0; g.NavJustMovedToKeyMods = 0;
g.NavJustMovedToIsTabbing = false; g.NavJustMovedToIsTabbing = false;
g.NavJustMovedToIsInit = true;
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0; g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
} }
@ -15153,6 +15181,7 @@ void ImGui::NavMoveRequestApplyResult()
g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToFocusScopeId = result->FocusScopeId;
g.NavJustMovedToKeyMods = g.NavMoveKeyMods; g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
g.NavJustMovedToIsInit = false;
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0; g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
//IMGUI_DEBUG_LOG_NAV("[nav] NavJustMovedFromFocusScopeId = 0x%08X, NavJustMovedToFocusScopeId = 0x%08X\n", g.NavJustMovedFromFocusScopeId, g.NavJustMovedToFocusScopeId); //IMGUI_DEBUG_LOG_NAV("[nav] NavJustMovedFromFocusScopeId = 0x%08X, NavJustMovedToFocusScopeId = 0x%08X\n", g.NavJustMovedFromFocusScopeId, g.NavJustMovedToFocusScopeId);
} }
@ -16079,17 +16108,9 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that live for 1 frame) flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that live for 1 frame)
const bool draw_target_rect = payload.Preview && !(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); const bool draw_target_rect = payload.Preview && !(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
if (draw_target_rect && g.DragDropTargetFullViewport != 0) if (draw_target_rect && g.DragDropTargetFullViewport != 0)
{ RenderDragDropTargetRectForViewport(g.DragDropTargetFullViewport, g.DragDropTargetRect);
ImGuiViewport* viewport = FindViewportByID(g.DragDropTargetFullViewport);
IM_ASSERT(viewport != NULL);
ImRect bb = g.DragDropTargetRect;
bb.Expand(-3.5f);
RenderDragDropTargetRectEx(GetForegroundDrawList(viewport), bb, g.Style.DragDropTargetRounding);
}
else if (draw_target_rect) else if (draw_target_rect)
{
RenderDragDropTargetRectForItem(r); RenderDragDropTargetRectForItem(r);
}
g.DragDropAcceptFrameCount = g.FrameCount; g.DragDropAcceptFrameCount = g.FrameCount;
if ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) && g.DragDropMouseButton == -1) if ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) && g.DragDropMouseButton == -1)
@ -16120,6 +16141,16 @@ void ImGui::RenderDragDropTargetRectForItem(const ImRect& bb)
window->DrawList->PopClipRect(); window->DrawList->PopClipRect();
} }
void ImGui::RenderDragDropTargetRectForViewport(ImGuiID viewport_id, const ImRect& bb)
{
ImGuiContext& g = *GImGui;
ImGuiViewport* viewport = FindViewportByID(viewport_id);
IM_ASSERT(viewport != NULL);
ImRect bb_padded = bb;
bb_padded.Expand(-g.Style.DragDropTargetPadding);
RenderDragDropTargetRectEx(GetForegroundDrawList(viewport), bb_padded, g.Style.DragDropTargetRounding);
}
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding) void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -16889,6 +16920,7 @@ void ImGuiPlatformIO::ClearPlatformHandlers()
Platform_OnChangedViewport = NULL; Platform_OnChangedViewport = NULL;
Platform_GetWindowWorkAreaInsets = NULL; Platform_GetWindowWorkAreaInsets = NULL;
Platform_CreateVkSurface = NULL; Platform_CreateVkSurface = NULL;
InitializeDefaultPlatformHandlers(*this); // Prevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation.
} }
void ImGuiPlatformIO::ClearRendererHandlers() void ImGuiPlatformIO::ClearRendererHandlers()
@ -16898,7 +16930,7 @@ void ImGuiPlatformIO::ClearRendererHandlers()
Renderer_CreateWindow = Renderer_DestroyWindow = NULL; Renderer_CreateWindow = Renderer_DestroyWindow = NULL;
Renderer_SetWindowSize = NULL; Renderer_SetWindowSize = NULL;
Renderer_RenderWindow = Renderer_SwapBuffers = NULL; Renderer_RenderWindow = Renderer_SwapBuffers = NULL;
DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = NULL; DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = DrawCallback_SetSamplerFromTex = NULL;
} }
ImGuiViewport* ImGui::GetMainViewport() ImGuiViewport* ImGui::GetMainViewport()
@ -21994,7 +22026,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* t
::CloseClipboard(); ::CloseClipboard();
} }
#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS) #elif defined(__APPLE__) && defined(TARGET_OS_OSX) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
#include <Carbon/Carbon.h> // Use old API to avoid need for separate .mm file #include <Carbon/Carbon.h> // Use old API to avoid need for separate .mm file
static PasteboardRef main_clipboard = 0; static PasteboardRef main_clipboard = 0;
@ -22166,6 +22198,15 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImG
#endif // Default IME handlers #endif // Default IME handlers
// Setup default ImGuiPlatformIO clipboard/IME handlers
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io)
{
platform_io.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl;
platform_io.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
platform_io.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] METRICS/DEBUGGER WINDOW // [SECTION] METRICS/DEBUGGER WINDOW
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -22584,7 +22625,7 @@ void ImGui::DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRe
Checkbox("Show used rect", &cfg->ShowTextureUsedRect); Checkbox("Show used rect", &cfg->ShowTextureUsedRect);
PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize)); PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize));
ImVec2 p = GetCursorScreenPos(); ImVec2 p = GetCursorScreenPos();
if (tex->WantDestroyNextFrame) if (tex->Status == ImTextureStatus_WantDestroy || tex->Status == ImTextureStatus_Destroyed)
Dummy(ImVec2((float)tex->Width, (float)tex->Height)); Dummy(ImVec2((float)tex->Width, (float)tex->Height));
else else
ImageWithBg(tex->GetTexRef(), ImVec2((float)tex->Width, (float)tex->Height), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); ImageWithBg(tex->GetTexRef(), ImVec2((float)tex->Width, (float)tex->Height), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImVec4(0.0f, 0.0f, 0.0f, 1.0f));

147
imgui.h
View File

@ -30,7 +30,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.93.0 WIP" #define IMGUI_VERSION "1.93.0 WIP"
#define IMGUI_VERSION_NUM 19294 #define IMGUI_VERSION_NUM 19297
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #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_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. #define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
@ -130,6 +130,16 @@ Index of this file:
#define IM_MSVC_RUNTIME_CHECKS_RESTORE #define IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif #endif
// Alternative to using a .natstepfilter file or other scripts in misc/debuggers/ to skip debug-stepping selected trivial functions.
// If you get a compiler error or warning related to use, please report it to us!
#if (defined(__clang__) && (__clang_major__ >= 7)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
#define IM_NODEBUGSTEP [[gnu::artificial]]
#elif defined(_MSC_VER) && (_MSC_VER >= 1915)
#define IM_NODEBUGSTEP __declspec(non_user_code)
#else
#define IM_NODEBUGSTEP
#endif
// Warnings // Warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (push) #pragma warning (push)
@ -300,8 +310,8 @@ IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec2 struct ImVec2
{ {
float x, y; float x, y;
constexpr ImVec2() : x(0.0f), y(0.0f) { } IM_NODEBUGSTEP constexpr inline ImVec2() : x(0.0f), y(0.0f) { }
constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { } IM_NODEBUGSTEP constexpr inline ImVec2(float _x, float _y) : x(_x), y(_y) { }
float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine. float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine.
float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; } float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; }
#ifdef IM_VEC2_CLASS_EXTRA #ifdef IM_VEC2_CLASS_EXTRA
@ -313,8 +323,8 @@ struct ImVec2
struct ImVec4 struct ImVec4
{ {
float x, y, z, w; float x, y, z, w;
constexpr ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { } IM_NODEBUGSTEP constexpr inline ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
constexpr ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { } IM_NODEBUGSTEP constexpr inline ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { }
#ifdef IM_VEC4_CLASS_EXTRA #ifdef IM_VEC4_CLASS_EXTRA
IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
#endif #endif
@ -1308,6 +1318,17 @@ enum ImGuiItemFlags_
ImGuiItemFlags_LiveEditOnInputText = 1 << 7, // true // InputText: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus. ImGuiItemFlags_LiveEditOnInputText = 1 << 7, // true // InputText: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
ImGuiItemFlags_LiveEditOnInputScalar = 1 << 8, // false // DragXXX, SliderXXX, InputScalar: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus. ImGuiItemFlags_LiveEditOnInputScalar = 1 << 8, // false // DragXXX, SliderXXX, InputScalar: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
ImGuiItemFlags_LiveEditOnInput = ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar, ImGuiItemFlags_LiveEditOnInput = ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar,
//---------------------------------------------------------------------------------
// [BETA] MixedValue mode used to represent a mixed/indeterminate state, typically for multi-selection.
// - Replace value display with "-" or a custom label.
// - Enter key validation apply an edit and return true even if value hasn't changed (in order to apply to all).
// - Supported by selected widgets: Checkbox, RadioButton, Sliders, Drags, Inputs, Combo.
// - Note: InputText-side Undo cannot be reliably combined with MixedValue + LiveEdit On:
// - Both the initial edit and subsequent undo/revert will typically make your app code write to all backing objects.
// - If you use MixedMode and the simplest solution is to ensure LiveEdit is off but widgets where this applies.
//---------------------------------------------------------------------------------
ImGuiItemFlags_MixedValue = 1 << 9, // false // [BETA] Represent a mixed/indeterminate value. Replace value label with "-" and apply edits on validation.
}; };
// Flags for ImGui::InputText() // Flags for ImGui::InputText()
@ -2345,13 +2366,13 @@ struct ImVector
inline int size_in_bytes() const { return Size * (int)sizeof(T); } inline int size_in_bytes() const { return Size * (int)sizeof(T); }
inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); } inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); }
inline int capacity() const { return Capacity; } inline int capacity() const { return Capacity; }
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } IM_NODEBUGSTEP inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } IM_NODEBUGSTEP inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
inline T* begin() { return Data; } IM_NODEBUGSTEP inline T* begin() { return Data; }
inline const T* begin() const { return Data; } IM_NODEBUGSTEP inline const T* begin() const { return Data; }
inline T* end() { return Data + Size; } IM_NODEBUGSTEP inline T* end() { return Data + Size; }
inline const T* end() const { return Data + Size; } IM_NODEBUGSTEP inline const T* end() const { return Data + Size; }
inline T& front() { IM_ASSERT(Size > 0); return Data[0]; } inline T& front() { IM_ASSERT(Size > 0); return Data[0]; }
inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; } inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; }
inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; } inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; }
@ -2462,7 +2483,7 @@ struct ImGuiStyle
float DockingSeparatorSize; // Thickness of resizing border between docked windows float DockingSeparatorSize; // Thickness of resizing border between docked windows
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later. float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later.
// Rendering & Tesselation // Rendering & Tessellation
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
@ -2898,30 +2919,27 @@ struct ImGuiOnceUponAFrame
operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }
}; };
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" // Helper: Parse and apply text filters e.g. 'aaa bbb' (all), 'aaa,bbb' (any), '-aaa' (exclude), '"Hello, world"' (exact sequence)
struct ImGuiTextFilterItem;
struct ImGuiTextFilter struct ImGuiTextFilter
{ {
IMGUI_API ImGuiTextFilter(const char* default_filter = ""); IMGUI_API ImGuiTextFilter(const char* default_filter = "");
IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const;
IMGUI_API void Build(); IMGUI_API void Build(); // Update internal data when filter changes
void Clear() { InputBuf[0] = 0; Build(); } inline void Clear() { InputBuf[0] = 0; Build(); } // Clear filter
bool IsActive() const { return !Filters.empty(); } inline bool IsActive() const { return _Items.Size != 0; } // Useful if you need e.g. an alternative code-path when there are no filters
// [Internal] // Helper to call InputText() + Build() when buffer is changed.
struct ImGuiTextRange IMGUI_API bool Draw(const char* label = "Filter");
{ IMGUI_API bool DrawWithHint(const char* label = "Filter", const char* hint = "incl -excl");
const char* b; #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
const char* e; inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); }
#endif
ImGuiTextRange() { b = e = NULL; } // Members
ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; } char InputBuf[256]; // User input buffer
bool empty() const { return b == e; } int _CountExclude; // [Internal] >= 0 count of leading exclude
IMGUI_API void split(char separator, ImVector<ImGuiTextRange>* out) const; ImVector<ImGuiTextFilterItem> _Items; // [Internal] Pre-parsed, trimmed, reordered items
};
char InputBuf[256];
ImVector<ImGuiTextRange>Filters;
int CountGrep;
}; };
// Helper: Growable text buffer for logging/accumulating text // Helper: Growable text buffer for logging/accumulating text
@ -3074,41 +3092,41 @@ struct ImGuiListClipper
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
// ImVec2 operators // ImVec2 operators
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); } IM_NODEBUGSTEP inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); } IM_NODEBUGSTEP inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); } IM_NODEBUGSTEP inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } IM_NODEBUGSTEP inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } IM_NODEBUGSTEP inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } IM_NODEBUGSTEP inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); } IM_NODEBUGSTEP inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
inline ImVec2 operator+(const ImVec2& lhs) { return lhs; } IM_NODEBUGSTEP inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); } IM_NODEBUGSTEP inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } IM_NODEBUGSTEP inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } IM_NODEBUGSTEP inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; } IM_NODEBUGSTEP inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
// ImVec4 operators // ImVec4 operators
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); } IM_NODEBUGSTEP inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); } IM_NODEBUGSTEP inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); } IM_NODEBUGSTEP inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } IM_NODEBUGSTEP inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } IM_NODEBUGSTEP inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } IM_NODEBUGSTEP inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); } IM_NODEBUGSTEP inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
inline ImVec4 operator+(const ImVec4& lhs) { return lhs; } IM_NODEBUGSTEP inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); } IM_NODEBUGSTEP inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; } IM_NODEBUGSTEP inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; } IM_NODEBUGSTEP inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; } IM_NODEBUGSTEP inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif #endif
@ -4303,6 +4321,7 @@ struct ImGuiPlatformIO
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state. ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear. ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point. ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
ImDrawCallback DrawCallback_SetSamplerFromTex; // Request backend to use sampler associated to texture - only available in some backends: OpenGL2/3 and SDLRenderer3.
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data. //ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -87,6 +87,7 @@ Index of this file:
// [SECTION] DemoWindowWidgetsImages() // [SECTION] DemoWindowWidgetsImages()
// [SECTION] DemoWindowWidgetsListBoxes() // [SECTION] DemoWindowWidgetsListBoxes()
// [SECTION] DemoWindowWidgetsLiveEdit() // [SECTION] DemoWindowWidgetsLiveEdit()
// [SECTION] DemoWindowWidgetsMixedValues()
// [SECTION] DemoWindowWidgetsMultiComponents() // [SECTION] DemoWindowWidgetsMultiComponents()
// [SECTION] DemoWindowWidgetsPlotting() // [SECTION] DemoWindowWidgetsPlotting()
// [SECTION] DemoWindowWidgetsProgressBars() // [SECTION] DemoWindowWidgetsProgressBars()
@ -1522,7 +1523,8 @@ static void DemoWindowWidgetsComboBoxes()
filter.Clear(); filter.Clear();
} }
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F);
filter.Draw("##Filter", -FLT_MIN); ImGui::SetNextItemWidth(-FLT_MIN);
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
for (int n = 0; n < IM_COUNTOF(items); n++) for (int n = 0; n < IM_COUNTOF(items); n++)
{ {
@ -2091,7 +2093,7 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
{ {
if (ImGui::TreeNode("Live Edit Flags")) if (ImGui::TreeNode("Live Edit Flags"))
{ {
IMGUI_DEMO_MARKER("Widgets/Live Edit Flgs"); IMGUI_DEMO_MARKER("Widgets/Live Edit Flags");
ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing."); ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing.");
@ -2121,6 +2123,65 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
} }
} }
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsMixedValues()
//-----------------------------------------------------------------------------
static void DemoWindowWidgetsMixedValues()
{
if (ImGui::TreeNode("Mixed Values"))
{
// This is designed for advanced property editors which are generally reusable and data-driven.
HelpMarker("Using ImGuiItemFlags_MixedValue.");
static bool use_liveedit = false;
static float items[3] = { 12.0f, 0.0f, 0.0f };
float* item_ref = &items[0];
ImGui::Checkbox("ImGuiItemFlags_LiveEditOnInput", &use_liveedit);
ImGui::SeparatorText("Scalar/Text Widgets");
const bool is_mixed = memcmp(&items[0], &items[1], sizeof(float)) != 0 || memcmp(&items[0], &items[2], sizeof(float)) != 0;
// Demonstrate Drags, Sliders, Inputs
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInput, use_liveedit);
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, is_mixed);
bool edited = false;
edited |= ImGui::DragFloat("DragFloat", item_ref);
edited |= ImGui::SliderFloat("SliderFloat", item_ref, 0.0f, 100.0f);
edited |= ImGui::InputFloat("InputFloat", item_ref, 1.0f);
if (edited)
for (float& item : items)
if (&item != item_ref)
item = *item_ref;
ImGui::PopItemFlag();
ImGui::Text("Underlying data:");
ImGui::InputFloat("item 0 (ref)", &items[0]);
ImGui::InputFloat("item 1", &items[1]);
ImGui::InputFloat("item 2", &items[2]);
ImGui::PopItemFlag();
// Demonstrate Checkbox(), RadioButton(), Combo(), ColorEdit4()
ImGui::SeparatorText("Others Widgets");
ImGui::Text("(note: edits are not applied in this demo)"); // <-- Would need more state tracking.
bool b_on = true, b_off = false;
ImGui::Checkbox("Checkbox On", &b_on);
ImGui::Checkbox("Checkbox Off", &b_off);
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
ImGui::Checkbox("Checkbox Mixed", &b_off);
ImGui::RadioButton("RadioButton Mixed", true);
ImGui::SameLine();
ImGui::RadioButton("RadioButton Mixed##2", true); // Showing 2 radio buttons makes the example more clear
int combo_idx = 0;
ImGui::Combo("Combo", &combo_idx, "One\0Two\0Three\0");
ImVec4 color(0.5f, 0.5f, 0.5f, 0.5f);
ImGui::ColorEdit4("ColorEdit4", &color.x);
ImGui::PopItemFlag();
ImGui::TreePop();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsMultiComponents() // [SECTION] DemoWindowWidgetsMultiComponents()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2301,12 +2362,14 @@ static void DemoWindowWidgetsQueryingStatuses()
}; };
static int item_type = 4; static int item_type = 4;
static bool item_disabled = false; static bool item_disabled = false;
static bool item_mixedvalue = false;
static bool liveedit_flags_override = false; static bool liveedit_flags_override = false;
static ImGuiItemFlags liveedit_flags = 0; static ImGuiItemFlags liveedit_flags = 0;
ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names)); ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
ImGui::SameLine(); ImGui::SameLine();
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered()."); HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
ImGui::Checkbox("Item Disabled", &item_disabled); ImGui::Checkbox("Item Disabled", &item_disabled);
ImGui::Checkbox("Item MixedValue", &item_mixedvalue);
ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override); ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override);
ImGui::SameLine(); ImGui::SameLine();
if (!liveedit_flags_override) if (!liveedit_flags_override)
@ -2331,6 +2394,8 @@ static void DemoWindowWidgetsQueryingStatuses()
static char str[16] = {}; static char str[16] = {};
if (item_disabled) if (item_disabled)
ImGui::BeginDisabled(true); ImGui::BeginDisabled(true);
if (item_mixedvalue)
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater) if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
@ -2414,6 +2479,8 @@ static void DemoWindowWidgetsQueryingStatuses()
ImGui::PopItemFlag(); ImGui::PopItemFlag();
ImGui::PopItemFlag(); ImGui::PopItemFlag();
} }
if (item_mixedvalue)
ImGui::PopItemFlag();
if (item_disabled) if (item_disabled)
ImGui::EndDisabled(); ImGui::EndDisabled();
@ -3764,11 +3831,13 @@ static void DemoWindowWidgetsTabs()
// but they tend to make more sense together) // but they tend to make more sense together)
static bool show_leading_button = true; static bool show_leading_button = true;
static bool show_trailing_button = true; static bool show_trailing_button = true;
static bool show_leading_trailing_tabs = false;
ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
ImGui::Checkbox("Show Leading+Trailing TabItem()", &show_leading_trailing_tabs);
// Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyShrink; static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyMixed;
EditTabBarFittingPolicyFlags(&tab_bar_flags); EditTabBarFittingPolicyFlags(&tab_bar_flags);
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
@ -3783,6 +3852,15 @@ static void DemoWindowWidgetsTabs()
ImGui::EndPopup(); ImGui::EndPopup();
} }
// Demo Leading/Trailing Tabs
if (show_leading_trailing_tabs)
{
if (ImGui::BeginTabItem("Leading", NULL, ImGuiTabItemFlags_Leading))
ImGui::EndTabItem();
if (ImGui::BeginTabItem("Trailing", NULL, ImGuiTabItemFlags_Trailing))
ImGui::EndTabItem();
}
// Demo Trailing Tabs: click the "+" button to add a new tab. // Demo Trailing Tabs: click the "+" button to add a new tab.
// (In your app you may want to use a font icon instead of the "+") // (In your app you may want to use a font icon instead of the "+")
// We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end. // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
@ -3951,14 +4029,24 @@ static void DemoWindowWidgetsTextFilter()
static ImGuiTextFilter filter; static ImGuiTextFilter filter;
ImGui::Text("Filter usage:\n" ImGui::Text("Filter usage:\n"
" \"\" display all lines\n" " \"\" display all lines\n"
" \"xxx\" display lines containing \"xxx\"\n" " xxx display lines containing \"xxx\"\n"
" \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" " xxx yyy display lines containing \"xxx\" and \"yyy\"\n"
" \"-xxx\" hide lines containing \"xxx\""); " \"xxx yyy\" display lines containing \"xxx yyy\"\n"
filter.Draw(); " xxx,yyy display lines containing \"xxx\" or \"yyy\"\n"
" -xxx hide lines containing \"xxx\"");
ImGui::SetNextItemWidth(-FLT_MIN);
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
if (ImGui::BeginChild("##items", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 15), ImGuiChildFlags_FrameStyle))
{
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
for (int i = 0; i < IM_COUNTOF(lines); i++) for (const char* item : lines)
if (filter.PassFilter(lines[i])) if (filter.PassFilter(item))
ImGui::BulletText("%s", lines[i]); ImGui::TextUnformatted(item);
for (const char* item : ExampleNames)
if (filter.PassFilter(item))
ImGui::TextUnformatted(item);
}
ImGui::EndChild();
ImGui::TreePop(); ImGui::TreePop();
} }
} }
@ -4591,6 +4679,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
DemoWindowWidgetsImages(); DemoWindowWidgetsImages();
DemoWindowWidgetsListBoxes(); DemoWindowWidgetsListBoxes();
DemoWindowWidgetsLiveEdit(demo_data); DemoWindowWidgetsLiveEdit(demo_data);
DemoWindowWidgetsMixedValues();
DemoWindowWidgetsMultiComponents(); DemoWindowWidgetsMultiComponents();
DemoWindowWidgetsPlotting(); DemoWindowWidgetsPlotting();
DemoWindowWidgetsProgressBars(); DemoWindowWidgetsProgressBars();
@ -8856,9 +8945,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
SameLine(); SetNextItemWidth(GetFontSize() * 10); Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); SameLine(); SetNextItemWidth(GetFontSize() * 10); Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
SameLine(); Checkbox("Only Modified Colors", &output_only_modified); SameLine(); Checkbox("Only Modified Colors", &output_only_modified);
static ImGuiTextFilter filter;
filter.Draw("Filter colors", GetFontSize() * 16);
static ImGuiColorEditFlags alpha_flags = 0; static ImGuiColorEditFlags alpha_flags = 0;
if (RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque)) { alpha_flags = ImGuiColorEditFlags_AlphaOpaque; } SameLine(); if (RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque)) { alpha_flags = ImGuiColorEditFlags_AlphaOpaque; } SameLine();
if (RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } SameLine(); if (RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } SameLine();
@ -8868,6 +8954,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
"Left-click on color square to open color picker,\n" "Left-click on color square to open color picker,\n"
"Right-click to open edit options menu."); "Right-click to open edit options menu.");
static ImGuiTextFilter filter;
SetNextItemWidth(-FLT_MIN);
filter.DrawWithHint("##FilterColors", "Filter Colors (incl -excl)");
SetNextWindowSizeConstraints(ImVec2(0.0f, GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX)); SetNextWindowSizeConstraints(ImVec2(0.0f, GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX));
BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
PushItemWidth(GetFontSize() * -12); PushItemWidth(GetFontSize() * -12);
@ -9280,7 +9370,10 @@ struct ExampleAppConsole
if (ImGui::Button("Options")) if (ImGui::Button("Options"))
ImGui::OpenPopup("Options"); ImGui::OpenPopup("Options");
ImGui::SameLine(); ImGui::SameLine();
Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
ImGui::SetNextItemWidth(-FLT_MIN);
Filter.DrawWithHint("##Filter", "Filter (incl -excl)");
ImGui::Separator(); ImGui::Separator();
// Reserve enough left-over height for 1 separator + 1 input text // Reserve enough left-over height for 1 separator + 1 input text
@ -9615,7 +9708,8 @@ struct ExampleAppLog
ImGui::SameLine(); ImGui::SameLine();
bool copy = ImGui::Button("Copy"); bool copy = ImGui::Button("Copy");
ImGui::SameLine(); ImGui::SameLine();
Filter.Draw("Filter", -100.0f); ImGui::SetNextItemWidth(-FLT_MIN);
Filter.DrawWithHint("##Filter", "Filter (incl -excl)");
ImGui::Separator(); ImGui::Separator();
@ -9810,7 +9904,7 @@ struct ExampleAppPropertyEditor
ImGui::Text("(%d root nodes)", root_node->Childs.Size); ImGui::Text("(%d root nodes)", root_node->Childs.Size);
ImGui::SetNextItemWidth(-FLT_MIN); ImGui::SetNextItemWidth(-FLT_MIN);
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) if (ImGui::InputTextWithHint("##Filter", "incl -excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
Filter.Build(); Filter.Build();
ImGui::PopItemFlag(); ImGui::PopItemFlag();

View File

@ -340,9 +340,9 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f); colors[ImGuiCol_TitleBg] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f); colors[ImGuiCol_TitleBgActive] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f); colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.43f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
@ -373,7 +373,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TabDimmedSelected] = ImLerp(colors[ImGuiCol_TabSelected], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_TabDimmedSelected] = ImLerp(colors[ImGuiCol_TabSelected], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.26f, 0.59f, 1.00f, 0.00f); colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.26f, 0.59f, 1.00f, 0.00f);
colors[ImGuiCol_DockingPreview] = colors[ImGuiCol_Header] * ImVec4(1.0f, 1.0f, 1.0f, 0.7f); colors[ImGuiCol_DockingPreview] = colors[ImGuiCol_Header] * ImVec4(1.0f, 1.0f, 1.0f, 0.7f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.68f, 0.69f, 0.73f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@ -705,7 +705,7 @@ void ImDrawList::PushTexture(ImTextureRef tex_ref)
_TextureStack.push_back(tex_ref); _TextureStack.push_back(tex_ref);
_CmdHeader.TexRef = tex_ref; _CmdHeader.TexRef = tex_ref;
if (tex_ref._TexData != NULL) if (tex_ref._TexData != NULL)
IM_ASSERT(tex_ref._TexData->WantDestroyNextFrame == false); IM_ASSERT(tex_ref._TexData->Status != ImTextureStatus_WantDestroy && tex_ref._TexData->Status != ImTextureStatus_Destroyed);
_OnChangedTexture(); _OnChangedTexture();
} }
@ -6225,26 +6225,33 @@ ImDrawFlags ImGui::CalcRoundingFlagsForRectInRect(const ImRect& r_in, const ImRe
// Helper for ColorPicker4() // Helper for ColorPicker4()
// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. // NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether. // Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.
// FIXME: uses ImGui::GetColorU32 void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float alpha, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags)
void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags)
{ {
if ((flags & ImDrawFlags_RoundCornersMask_) == 0) if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
flags = ImDrawFlags_RoundCornersDefault_; flags = ImDrawFlags_RoundCornersAll;
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
{ {
ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); IM_ASSERT(alpha >= 0.0f && alpha <= 1.0f);
ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); const ImU32 a_mask = (ImU32)(alpha * 255.0f) << IM_COL32_A_SHIFT;
ImU32 col_bg1 = (ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col) & ~IM_COL32_A_MASK) | a_mask;
ImU32 col_bg2 = (ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col) & ~IM_COL32_A_MASK) | a_mask;
const bool dual_layer = (alpha == 1.0f); // Dual layer is faster but incorrect if blending.
if (dual_layer)
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags); draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
int yi = 0; int yi = 0;
for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
{ {
float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); float y1 = ImClamp((float)(int)y, p_min.y, p_max.y), y2 = ImMin((float)(int)(y + grid_step), p_max.y);
if (y2 <= y1) if (y2 <= y1)
continue; continue;
for (float x = p_min.x + grid_off.x + ((yi ^ 1) & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
const float x_start_off = dual_layer ? (((yi ^ 1) & 1) * grid_step) : 0.0f;
const float x_step = dual_layer ? (grid_step * 2.0f) : (grid_step);
int xi = 0;
for (float x = p_min.x + grid_off.x + x_start_off; x < p_max.x; x += x_step, xi++)
{ {
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); float x1 = ImClamp((float)(int)x, p_min.x, p_max.x), x2 = ImMin((float)(int)(x + grid_step), p_max.x);
if (x2 <= x1) if (x2 <= x1)
continue; continue;
ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; // FIXME: Could use CalcRoundingFlagsForRectInRect() ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; // FIXME: Could use CalcRoundingFlagsForRectInRect()
@ -6253,7 +6260,8 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
// Combine flags // Combine flags
cell_flags = (flags == ImDrawFlags_RoundCornersNone || cell_flags == ImDrawFlags_RoundCornersNone) ? ImDrawFlags_RoundCornersNone : (cell_flags & flags); cell_flags = (flags == ImDrawFlags_RoundCornersNone || cell_flags == ImDrawFlags_RoundCornersNone) ? ImDrawFlags_RoundCornersNone : (cell_flags & flags);
draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding, cell_flags); ImU32 col_bg = dual_layer ? col_bg2 : (((yi + xi) & 1) ? col_bg2 : col_bg1);
draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg, rounding, cell_flags);
} }
} }
} }

View File

@ -194,6 +194,7 @@ struct ImGuiWindow; // Storage for one window
struct ImGuiWindowDockStyle; // Storage for window-style data which needs to be stored for docking purpose struct ImGuiWindowDockStyle; // Storage for window-style data which needs to be stored for docking purpose
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window) struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
struct ImGuiWindowStackData; // Storage for each window pushed into the stack
// Enumerations // Enumerations
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
@ -378,6 +379,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
// - Helper: ImPool<> // - Helper: ImPool<>
// - Helper: ImChunkStream<> // - Helper: ImChunkStream<>
// - Helper: ImGuiTextIndex // - Helper: ImGuiTextIndex
// - Helper: ImGuiTextFilterItem
// - Helper: ImGuiStorage // - Helper: ImGuiStorage
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -417,7 +419,7 @@ IMGUI_API const char* ImStrSkipBlank(const char* str);
IMGUI_API int ImStrlenW(const ImWchar* str); // Computer string length (ImWchar string) IMGUI_API int ImStrlenW(const ImWchar* str); // Computer string length (ImWchar string)
IMGUI_API const char* ImStrbol(const char* buf_mid_line, const char* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStrbol(const char* buf_mid_line, const char* buf_begin); // Find beginning-of-line
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; } inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c & ~32 : c; }
inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); }
@ -576,25 +578,25 @@ IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec1 struct ImVec1
{ {
float x; float x;
constexpr ImVec1() : x(0.0f) { } IM_NODEBUGSTEP constexpr inline ImVec1() : x(0.0f) { }
constexpr ImVec1(float _x) : x(_x) { } IM_NODEBUGSTEP constexpr inline ImVec1(float _x) : x(_x) { }
}; };
// Helper: ImVec2i (2D vector, integer) // Helper: ImVec2i (2D vector, integer)
struct ImVec2i struct ImVec2i
{ {
int x, y; int x, y;
constexpr ImVec2i() : x(0), y(0) {} IM_NODEBUGSTEP constexpr inline ImVec2i() : x(0), y(0) {}
constexpr ImVec2i(int _x, int _y) : x(_x), y(_y) {} IM_NODEBUGSTEP constexpr inline ImVec2i(int _x, int _y) : x(_x), y(_y) {}
}; };
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage) // Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
struct ImVec2ih struct ImVec2ih
{ {
short x, y; short x, y;
constexpr ImVec2ih() : x(0), y(0) {} IM_NODEBUGSTEP constexpr inline ImVec2ih() : x(0), y(0) {}
constexpr ImVec2ih(short _x, short _y) : x(_x), y(_y) {} IM_NODEBUGSTEP constexpr inline ImVec2ih(short _x, short _y) : x(_x), y(_y) {}
constexpr explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {} IM_NODEBUGSTEP constexpr inline explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {}
}; };
// Helper: ImRect (2D axis aligned bounding-box) // Helper: ImRect (2D axis aligned bounding-box)
@ -604,10 +606,10 @@ struct IMGUI_API ImRect
ImVec2 Min; // Upper-left ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right ImVec2 Max; // Lower-right
constexpr ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {} IM_NODEBUGSTEP constexpr inline ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
constexpr ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} IM_NODEBUGSTEP constexpr inline ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
constexpr ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} IM_NODEBUGSTEP constexpr inline ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
constexpr ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} IM_NODEBUGSTEP constexpr inline ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
@ -709,13 +711,13 @@ struct ImSpan
inline bool empty() const { return Data == DataEnd; } inline bool empty() const { return Data == DataEnd; }
inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); } inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); } inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
inline T* begin() { return Data; } IM_NODEBUGSTEP inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
inline const T* begin() const { return Data; } IM_NODEBUGSTEP inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
inline T* end() { return DataEnd; } IM_NODEBUGSTEP inline T* begin() { return Data; }
inline const T* end() const { return DataEnd; } IM_NODEBUGSTEP inline const T* begin() const { return Data; }
IM_NODEBUGSTEP inline T* end() { return DataEnd; }
IM_NODEBUGSTEP inline const T* end() const { return DataEnd; }
// Utilities // Utilities
inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; } inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; }
@ -846,6 +848,15 @@ struct ImGuiTextIndex
void append(const char* base, int old_size, int new_size); void append(const char* base, int old_size, int new_size);
}; };
// [Internal] Types
struct ImGuiTextFilterItem
{
const char* Begin;
int Len;
int CountInclude; // >0 when beginning of an AND chain.
ImGuiTextFilterItem(const char* b, const char* e) { IM_ASSERT(e > b); Begin = b; Len = (int)(e - b); CountInclude = 0; }
};
// Helper: ImGuiPackedDate (sizeof() == 2) // Helper: ImGuiPackedDate (sizeof() == 2)
// Store a date in a way that is efficient to read/write in text form. If we stored e.g. number of days since Epoch we'd need costlier back and forth. // Store a date in a way that is efficient to read/write in text form. If we stored e.g. number of days since Epoch we'd need costlier back and forth.
// This is specifically designed to be able to prune old .ini data. // This is specifically designed to be able to prune old .ini data.
@ -943,6 +954,8 @@ struct ImFontStackData
// [SECTION] Style support // [SECTION] Style support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define ImGuiCol_TextMixedValue ImGuiCol_TextDisabled
struct ImGuiStyleVarInfo struct ImGuiStyleVarInfo
{ {
ImU32 Count : 8; // 1+ ImU32 Count : 8; // 1+
@ -1004,7 +1017,6 @@ enum ImGuiItemFlagsPrivate_
{ {
// Controlled by user // Controlled by user
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable() ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame. ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false). ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
@ -1094,12 +1106,6 @@ enum ImGuiButtonFlagsPrivate_
//ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4 //ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4
}; };
// Extend ImGuiComboFlags_
enum ImGuiComboFlagsPrivate_
{
ImGuiComboFlags_CustomPreview = 1 << 20, // enable BeginComboPreview()
};
// Extend ImGuiSliderFlags_ // Extend ImGuiSliderFlags_
enum ImGuiSliderFlagsPrivate_ enum ImGuiSliderFlagsPrivate_
{ {
@ -1194,6 +1200,10 @@ enum ImGuiPlotType
ImGuiPlotType_Histogram, ImGuiPlotType_Histogram,
}; };
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//ImGuiComboFlags_CustomPreview = 1 << 20, // enable BeginComboPreview() // [Obsoleted in 1.93.0] Unnecessary: can now use BeginComboPreview() without a flag.
#endif
// Storage data for BeginComboPreview()/EndComboPreview() // Storage data for BeginComboPreview()/EndComboPreview()
struct IMGUI_API ImGuiComboPreviewData struct IMGUI_API ImGuiComboPreviewData
{ {
@ -1202,7 +1212,10 @@ struct IMGUI_API ImGuiComboPreviewData
ImVec2 BackupCursorMaxPos; ImVec2 BackupCursorMaxPos;
ImVec2 BackupCursorPosPrevLine; ImVec2 BackupCursorPosPrevLine;
float BackupPrevLineTextBaseOffset; float BackupPrevLineTextBaseOffset;
ImGuiLayoutType BackupLayout; float BackupWorkRectMaxX;
float BackupContentRectMaxX;
ImGuiLayoutType BackupLayout : 8;
int WithinPreview : 2;
ImGuiComboPreviewData() { memset((void*)this, 0, sizeof(*this)); } ImGuiComboPreviewData() { memset((void*)this, 0, sizeof(*this)); }
}; };
@ -1291,6 +1304,7 @@ struct IMGUI_API ImGuiInputTextState
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool EditedBefore; // edited since activated bool EditedBefore; // edited since activated
bool EditedThisFrame; // edited this frame bool EditedThisFrame; // edited this frame
bool ValidatedThisFrame;
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version. bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s
int ReloadSelectionStart; int ReloadSelectionStart;
@ -1476,7 +1490,7 @@ struct IMGUI_API ImGuiErrorRecoveryState
ImGuiErrorRecoveryState() { memset((void*)this, 0, sizeof(*this)); } ImGuiErrorRecoveryState() { memset((void*)this, 0, sizeof(*this)); }
}; };
// Data saved for each window pushed into the stack // Storage for each window pushed into the stack.
struct ImGuiWindowStackData struct ImGuiWindowStackData
{ {
ImGuiWindow* Window; ImGuiWindow* Window;
@ -1484,6 +1498,7 @@ struct ImGuiWindowStackData
ImGuiErrorRecoveryState StackSizesInBegin; // Store size of various stacks for asserting ImGuiErrorRecoveryState StackSizesInBegin; // Store size of various stacks for asserting
bool DisabledOverrideReenable; // Non-child window override disabled flag bool DisabledOverrideReenable; // Non-child window override disabled flag
float DisabledOverrideReenableAlphaBackup; float DisabledOverrideReenableAlphaBackup;
ImRect ParentLastComboPreviewRect;
}; };
struct ImGuiShrinkWidthItem struct ImGuiShrinkWidthItem
@ -2180,8 +2195,9 @@ struct ImGuiViewportP : public ImGuiViewport
float LastAlpha; float LastAlpha;
bool LastFocusedHadNavWindow;// Instead of maintaining a LastFocusedWindow (which may harder to correctly maintain), we merely store weither NavWindow != NULL last time the viewport was focused. bool LastFocusedHadNavWindow;// Instead of maintaining a LastFocusedWindow (which may harder to correctly maintain), we merely store weither NavWindow != NULL last time the viewport was focused.
short PlatformMonitor; short PlatformMonitor;
float BgFgDrawListsLastTimeActive[2]; // Last frame number the background (0) and foreground (1) draw lists were used
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
int BgFgDrawListsLastFrameActive[2]; // Last frame the background (0) and foreground (1) draw lists were used.
float BgFgDrawListsLastTimeActive[2]; // Timestamps for Gc.
ImDrawData DrawDataP; ImDrawData DrawDataP;
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
ImVec2 LastPlatformPos; ImVec2 LastPlatformPos;
@ -2197,7 +2213,7 @@ struct ImGuiViewportP : public ImGuiViewport
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
ImVec2 BuildWorkInsetMax; // " ImVec2 BuildWorkInsetMax; // "
ImGuiViewportP() { Window = NULL; Idx = -1; LastFrameActive = LastFocusedStampCount = -1; BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0f; LastNameHash = 0; Alpha = LastAlpha = 1.0f; LastFocusedHadNavWindow = false; PlatformMonitor = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; LastPlatformPos = LastPlatformSize = LastRendererSize = ImVec2(FLT_MAX, FLT_MAX); } ImGuiViewportP() { Window = NULL; Idx = -1; LastFrameActive = LastFocusedStampCount = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; LastFocusedHadNavWindow = false; PlatformMonitor = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; BgFgDrawListsLastFrameActive[0] = BgFgDrawListsLastFrameActive[1] = -1; BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0; LastPlatformPos = LastPlatformSize = LastRendererSize = ImVec2(FLT_MAX, FLT_MAX); }
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); } ~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
void ClearRequestFlags() { PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; } void ClearRequestFlags() { PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; }
@ -2501,6 +2517,7 @@ struct ImGuiContext
ImVec2 WheelingAxisAvg; ImVec2 WheelingAxisAvg;
// Item/widgets state and tracking information // Item/widgets state and tracking information
const char* MixedValueLabel; // Value replacement when displaying a mixed value. Default to "-" (Unreal uses "Multiple values", Unity uses "---"). May be interpreted as a format: must not contain single %. Set to NULL to display original value.
ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier
ImGuiID DebugHookIdInfoId; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line] ImGuiID DebugHookIdInfoId; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredId; // Hovered widget, filled during the frame
@ -2644,6 +2661,7 @@ struct ImGuiContext
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyChord NavJustMovedToKeyMods; ImGuiKeyChord NavJustMovedToKeyMods;
bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags. bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
bool NavJustMovedToIsInit; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData. bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
// Navigation: extra config options (will be made public eventually) // Navigation: extra config options (will be made public eventually)
@ -2900,7 +2918,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
int TreeDepth; // Current tree depth. int TreeDepth; // Current tree depth.
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. Sync any changes with TREE_NODE_MAX_DEPTH/TREE_NODE_GET_DEPTH_MASK!
ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set. ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set.
ImVector<ImGuiWindow*> ChildWindows; ImVector<ImGuiWindow*> ChildWindows;
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
@ -3581,7 +3599,7 @@ namespace ImGui
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
IMGUI_API ImGuiIO& GetIO(ImGuiContext* ctx); IMGUI_API ImGuiIO& GetIO(ImGuiContext* ctx);
IMGUI_API ImGuiPlatformIO& GetPlatformIO(ImGuiContext* ctx); IMGUI_API ImGuiPlatformIO& GetPlatformIO(ImGuiContext* ctx);
inline float GetScale() { ImGuiContext& g = *GImGui; return g.Style._MainScale; } // FIXME-DPI: I don't want to formalize this just yet. Because reasons. Please don't use. inline float GetScale() { ImGuiContext& g = *GImGui; return g.Style._MainScale; } // FIXME-DPI: PLEASE DO NOT USE. I don't want to formalize this just yet. Because reasons.
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
@ -3771,7 +3789,7 @@ namespace ImGui
// Combos // Combos
IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);
IMGUI_API bool BeginComboPreview(); IMGUI_API bool BeginComboPreview(); // Submit preview contents a combo. Call this after EndCombo() to display contents that's more than just a text label.
IMGUI_API void EndComboPreview(); IMGUI_API void EndComboPreview();
// Keyboard/Gamepad Navigation // Keyboard/Gamepad Navigation
@ -3959,6 +3977,7 @@ namespace ImGui
IMGUI_API void ClearDragDrop(); IMGUI_API void ClearDragDrop();
IMGUI_API bool IsDragDropPayloadBeingAccepted(); IMGUI_API bool IsDragDropPayloadBeingAccepted();
IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb); IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb);
IMGUI_API void RenderDragDropTargetRectForViewport(ImGuiID viewport_id, const ImRect& bb);
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding); IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding);
// Typing-Select API // Typing-Select API
@ -3992,6 +4011,7 @@ namespace ImGui
IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar); IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar);
inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); } inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); }
IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API ImVec2 TabBarGetTabPos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window); IMGUI_API void TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window);
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
@ -4018,7 +4038,7 @@ namespace ImGui
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding); IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float alpha, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None, float rounding = -1.0f); // Navigation highlight IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None, float rounding = -1.0f); // Navigation highlight
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4 inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4

View File

@ -1405,7 +1405,7 @@ bool ImGui::RadioButton(const char* label, bool active)
RenderNavCursor(total_bb, id); RenderNavCursor(total_bb, id);
const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius); const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
if (active) if (active && (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) == 0)
{ {
const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f)); const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f));
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark)); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
@ -1958,7 +1958,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
if (flags & ImGuiComboFlags_WidthFitPreview) if (flags & ImGuiComboFlags_WidthFitPreview)
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0); IM_ASSERT((flags & ImGuiComboFlags_NoPreview) == 0);
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const char* label_end = FindRenderedTextEnd(label); const char* label_end = FindRenderedTextEnd(label);
@ -1998,13 +1998,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
} }
RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding); RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
// Custom preview // Store geometry for BeginComboPreview() - only necessary when visible.
if (flags & ImGuiComboFlags_CustomPreview) g.ComboPreviewData.PreviewRect = (flags & ImGuiComboFlags_NoPreview) ? ImRect() : ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
{
g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
preview_value = NULL;
}
// Render preview and label // Render preview and label
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
@ -2086,6 +2081,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
return false; return false;
} }
g.BeginComboDepth++; g.BeginComboDepth++;
g.CurrentWindowStack.back().ParentLastComboPreviewRect = g.ComboPreviewData.PreviewRect;
return true; return true;
} }
@ -2093,6 +2089,7 @@ void ImGui::EndCombo()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.BeginComboDepth--; g.BeginComboDepth--;
g.ComboPreviewData.PreviewRect = g.CurrentWindowStack.back().ParentLastComboPreviewRect;
char name[16]; char name[16];
ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // FIXME: Move those to helpers? ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // FIXME: Move those to helpers?
if (strcmp(g.CurrentWindow->Name, name) != 0) if (strcmp(g.CurrentWindow->Name, name) != 0)
@ -2100,19 +2097,26 @@ void ImGui::EndCombo()
EndPopup(); EndPopup();
} }
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements // Submit preview contents for BeginCombo()/EndCombo(), to display contents that's more than just a text label.
// (Experimental, see GitHub issues: #1658, #4168) // - [BETA] See GitHub issues: #1658, #4168.
// - Make sure you call this after EndCombo().
// - The preview is designed to only host non-interactive elements.
// - Not compatible with ImGuiComboFlags_WidthFitPreview.
// - 2026-09-08 (1.93.0): removed ImGuiComboFlags_CustomPreview. You can use BeginComboPreview()/EndComboPreview() without an extra flag.
bool ImGui::BeginComboPreview() bool ImGui::BeginComboPreview()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
if (window->SkipItems || !(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)) if (window->SkipItems || !(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible))
return false; return false;
IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag? ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
if (!window->ClipRect.Overlaps(preview_data->PreviewRect)) // Narrower test (optional) if (!window->ClipRect.Overlaps(preview_data->PreviewRect) || preview_data->PreviewRect.GetWidth() <= 0.0f) // Narrower test (optional) + handle _NoPreview
return false; return false;
IM_ASSERT_USER_ERROR_RETV(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y, false,
"Call BeginComboPreview() after BeginCombo(), not after EndCombo()!"); // Calling after EndCombo() works only if you don't nest combos.
IM_ASSERT_USER_ERROR_RETV(preview_data->WithinPreview == false, false,
"Cannot recurse BeginComboPreview(): call EndComboPreview() before opening another combo.");
// FIXME: This could be contained in a PushWorkRect() api // FIXME: This could be contained in a PushWorkRect() api
preview_data->BackupCursorPos = window->DC.CursorPos; preview_data->BackupCursorPos = window->DC.CursorPos;
@ -2120,6 +2124,10 @@ bool ImGui::BeginComboPreview()
preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine; preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
preview_data->BackupLayout = window->DC.LayoutType; preview_data->BackupLayout = window->DC.LayoutType;
preview_data->WithinPreview = true;
preview_data->BackupWorkRectMaxX = window->WorkRect.Max.x;
preview_data->BackupContentRectMaxX = window->ContentRegionRect.Max.x;
window->WorkRect.Max.x = window->ContentRegionRect.Max.x = preview_data->PreviewRect.Max.x - g.Style.FramePadding.x;
window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding; window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;
window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.LayoutType = ImGuiLayoutType_Horizontal;
@ -2145,12 +2153,14 @@ void ImGui::EndComboPreview()
} }
PopClipRect(); PopClipRect();
window->DC.CursorPos = preview_data->BackupCursorPos; window->DC.CursorPos = preview_data->BackupCursorPos;
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos); window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos); // No need to do the same with IdealMaxPos
window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine; window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;
window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset; window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;
window->WorkRect.Max.x = preview_data->BackupWorkRectMaxX;
window->ContentRegionRect.Max.x = preview_data->BackupContentRectMaxX;
window->DC.LayoutType = preview_data->BackupLayout; window->DC.LayoutType = preview_data->BackupLayout;
window->DC.IsSameLine = false; window->DC.IsSameLine = false;
preview_data->PreviewRect = ImRect(); preview_data->WithinPreview = false;
} }
// Getter for the old Combo() API: const char*[] // Getter for the old Combo() API: const char*[]
@ -2183,7 +2193,9 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo
// Call the getter to obtain the preview string which is a parameter to BeginCombo() // Call the getter to obtain the preview string which is a parameter to BeginCombo()
const char* preview_value = NULL; const char* preview_value = NULL;
if (*current_item >= 0 && *current_item < items_count) if ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_MixedValue)
preview_value = "";
else if (*current_item >= 0 && *current_item < items_count)
preview_value = getter(user_data, *current_item); preview_value = getter(user_data, *current_item);
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
@ -2667,19 +2679,39 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
return true; return true;
} }
static bool ShortcutsForCancel(ImGuiID id)
{
ImGuiContext& g = *GImGui;
bool is_cancel_with_keyboard = ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_None, id);
bool is_cancel_with_gamepad = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0 && ImGui::Shortcut(ImGuiKey_NavGamepadCancel, ImGuiInputFlags_None, id);
bool is_cancel_with_mouse = ImGui::IsMouseReleased(ImGuiMouseButton_Right, id);
if (is_cancel_with_mouse)
ImGui::SetKeyOwner(ImGuiKey_MouseRight, id);
return is_cancel_with_keyboard || is_cancel_with_gamepad || is_cancel_with_mouse;
}
bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
{ {
// Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
// Things we can do easily outside the DragBehaviorT<> template, saves code generation.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.ActiveId == id) if (g.ActiveId == id)
{ {
// Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation.
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
ClearActiveID(); ClearActiveID();
else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
ClearActiveID(); ClearActiveID();
if (ShortcutsForCancel(id) && g.ActiveId == id) //-V560
{
// Canceling action reverts to initial value
size_t data_size = DataTypeGetInfo(data_type)->Size;
bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
ClearActiveID();
return value_changed;
}
} }
if (g.ActiveId != id) if (g.ActiveId != id)
return false; return false;
@ -2802,11 +2834,16 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
MarkItemEdited(id); MarkItemEdited(id);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
if (g.LogEnabled) if (g.LogEnabled)
LogSetNextTextDecoration("{", "}"); LogSetNextTextDecoration("{", "}");
if (is_mixed)
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
if (is_mixed)
PopStyleColor();
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
@ -3013,7 +3050,7 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
result = 0.0f; // Workaround for values that are in-range but below our fudge result = 0.0f; // Workaround for values that are in-range but below our fudge
else if (v_clamped >= v_max_fudged) else if (v_clamped >= v_max_fudged)
result = 1.0f; // Workaround for values that are in-range but above our fudge result = 1.0f; // Workaround for values that are in-range but above our fudge
else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions else if (((FLOATTYPE)v_min * (FLOATTYPE)v_max) < 0.0f) // Range crosses zero, so split into two portions
{ {
float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine) float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine)
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
@ -3067,7 +3104,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range
if ((v_min * v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts if (((FLOATTYPE)v_min * (FLOATTYPE)v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts
{ {
float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
@ -3092,13 +3129,13 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
{ {
result = ImLerp(v_min, v_max, t); result = ImLerp(v_min, v_max, t);
} }
else if (t < 1.0) else // t is already < 1.0 here
{ {
// - For integer values we want the clicking position to match the grab box so we round above // - For integer values we want the clicking position to match the grab box so we round above
// This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
// - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64 // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64
// range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits. // range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits.
FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t; FLOATTYPE v_new_off_f = (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min) * (FLOATTYPE)t;
result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5))); result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5)));
} }
} }
@ -3147,37 +3184,24 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
float clicked_t = 0.0f; float clicked_t = 0.0f;
if (g.ActiveIdSource == ImGuiInputSource_Mouse) if (g.ActiveIdSource == ImGuiInputSource_Mouse)
{ {
if (!g.IO.MouseDown[0]) const float mouse_pos = g.IO.MousePos[axis];
{
ClearActiveID();
}
else
{
const float mouse_abs_pos = g.IO.MousePos[axis];
if (g.ActiveIdIsJustActivated) if (g.ActiveIdIsJustActivated)
{ {
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize); float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if (axis == ImGuiAxis_Y) if (axis == ImGuiAxis_Y)
grab_t = 1.0f - grab_t; grab_t = 1.0f - grab_t;
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
const bool clicked_around_grab = (mouse_abs_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_abs_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here. const bool clicked_around_grab = (mouse_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here.
g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_abs_pos - grab_pos : 0.0f; g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_pos - grab_pos : 0.0f;
} }
if (slider_usable_sz > 0.0f) if (slider_usable_sz > 0.0f)
clicked_t = ImSaturate((mouse_abs_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz); clicked_t = ImSaturate((mouse_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz);
if (axis == ImGuiAxis_Y) if (axis == ImGuiAxis_Y)
clicked_t = 1.0f - clicked_t; clicked_t = 1.0f - clicked_t;
set_new_value = true; set_new_value = true;
} }
}
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
if (g.ActiveIdIsJustActivated)
{
g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation
g.SliderCurrentAccumDirty = false;
}
float input_delta = (axis == ImGuiAxis_X) ? GetNavTweakPressedAmount(axis) : -GetNavTweakPressedAmount(axis); float input_delta = (axis == ImGuiAxis_X) ? GetNavTweakPressedAmount(axis) : -GetNavTweakPressedAmount(axis);
if (input_delta != 0.0f) if (input_delta != 0.0f)
{ {
@ -3205,11 +3229,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
} }
float delta = g.SliderCurrentAccum; float delta = g.SliderCurrentAccum;
if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) if (g.SliderCurrentAccumDirty)
{
ClearActiveID();
}
else if (g.SliderCurrentAccumDirty)
{ {
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize); clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
@ -3235,7 +3255,6 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
else else
g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta); g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta);
} }
g.SliderCurrentAccumDirty = false; g.SliderCurrentAccumDirty = false;
} }
} }
@ -3290,6 +3309,33 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
IM_ASSERT((flags & ImGuiSliderFlags_WrapAround) == 0); // Not supported by SliderXXX(), only by DragXXX() IM_ASSERT((flags & ImGuiSliderFlags_WrapAround) == 0); // Not supported by SliderXXX(), only by DragXXX()
// Things we can do easily outside the SliderBehaviorT<> template, saves code generation.
ImGuiContext& g = *GImGui;
if (g.ActiveId == id)
{
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
ClearActiveID();
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{
if (g.ActiveIdIsJustActivated)
{
g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation
g.SliderCurrentAccumDirty = false;
}
if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
ClearActiveID();
}
if (ShortcutsForCancel(id) && g.ActiveId == id) //-V560
{
// Canceling action reverts to initial value
size_t data_size = DataTypeGetInfo(data_type)->Size;
bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
ClearActiveID();
return value_changed;
}
}
switch (data_type) switch (data_type)
{ {
case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
@ -3400,11 +3446,16 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
if (g.LogEnabled) if (g.LogEnabled)
LogSetNextTextDecoration("{", "}"); LogSetNextTextDecoration("{", "}");
if (is_mixed)
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
if (is_mixed)
PopStyleColor();
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
@ -3554,9 +3605,15 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
// For the vertical slider we allow centered text to overlap the frame padding // For the vertical slider we allow centered text to overlap the frame padding
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
char value_buf[64]; char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format); const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
if (is_mixed)
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f)); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
if (is_mixed)
PopStyleColor();
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
@ -3794,6 +3851,10 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
// Only mark as edited if new value is different // Only mark as edited if new value is different
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited; g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue)
if (ImGuiInputTextState* state = GetInputTextState(g.LastItemData.ID))
value_changed |= (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (state->EditedThisFrame | state->ValidatedThisFrame) : state->ValidatedThisFrame;
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
return value_changed; return value_changed;
@ -3870,6 +3931,9 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL); value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
} }
} }
if (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue)
if (ImGuiInputTextState* state = GetInputTextState(g.LastItemData.ID))
value_changed |= (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (state->EditedThisFrame | state->ValidatedThisFrame) : state->ValidatedThisFrame;
// Step buttons // Step buttons
if (has_step_buttons) if (has_step_buttons)
@ -4835,6 +4899,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0; const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
if (is_resizable) if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag! IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
@ -4921,7 +4986,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!is_multiline) if (!is_multiline)
{ {
if (flags & ImGuiInputTextFlags_AutoSelectAll) if ((flags & ImGuiInputTextFlags_AutoSelectAll) || is_mixed)
select_all = true; select_all = true;
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
select_all = true; select_all = true;
@ -4999,7 +5064,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Select the buffer to render. // Select the buffer to render.
const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state; const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
// Password pushes a temporary font with only a fallback glyph // Password pushes a temporary font with only a fallback glyph
if (is_password && !is_displaying_hint) if (is_password && !is_displaying_hint)
@ -5008,6 +5073,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (state != NULL && state->ID == id) if (state != NULL && state->ID == id)
{ {
state->Flags = flags; state->Flags = flags;
state->EditedThisFrame = state->ValidatedThisFrame = false;
//state->LastFrameActive = g.FrameCount; //state->LastFrameActive = g.FrameCount;
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset) // Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset)
@ -5023,7 +5089,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.ActiveId == id) if (g.ActiveId == id)
{ {
IM_ASSERT(state != NULL); IM_ASSERT(state != NULL);
state->EditedThisFrame = false;
state->BufCapacity = buf_size; state->BufCapacity = buf_size;
state->WrapWidth = wrap_width; state->WrapWidth = wrap_width;
@ -5426,7 +5491,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText) if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText)
{ {
// Apply when modified // Apply when modified
if (strcmp(state->TextSrc, buf) != 0) if (strcmp(state->TextSrc, buf) != 0 || (is_mixed && (state->EditedThisFrame || validated)))
{ {
apply_new_text = state->TextSrc; apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen; apply_new_text_length = state->TextLen;
@ -5436,7 +5501,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else else
{ {
// Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert) // Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert)
value_changed = ((validated || clear_active_id || revert_edit) && strcmp(state->TextSrc, buf) != 0); value_changed = (validated || clear_active_id || revert_edit) && (strcmp(state->TextSrc, buf) != 0 || (is_mixed && validated));
apply_new_text = value_changed ? state->TextSrc : NULL; apply_new_text = value_changed ? state->TextSrc : NULL;
apply_new_text_length = value_changed ? state->TextLen : 0; apply_new_text_length = value_changed ? state->TextLen : 0;
} }
@ -5521,7 +5586,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Display hint when contents is empty // Display hint when contents is empty
// At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368) // At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368)
const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
if (new_is_displaying_hint != is_displaying_hint) if (new_is_displaying_hint != is_displaying_hint)
{ {
if (is_password && !is_displaying_hint) if (is_password && !is_displaying_hint)
@ -5530,10 +5595,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_password && !is_displaying_hint) if (is_password && !is_displaying_hint)
PushPasswordFont(); PushPasswordFont();
} }
if (is_displaying_hint) const bool is_displaying_mixed = is_mixed && g.ActiveId != id && apply_new_text == NULL;
if (is_displaying_mixed && g.MixedValueLabel != NULL)
{
buf_display = g.MixedValueLabel;
buf_display_end = buf_display + strlen(g.MixedValueLabel);
render_cursor = render_selection = false;
}
else if (is_displaying_hint)
{ {
buf_display = hint; buf_display = hint;
buf_display_end = hint + ImStrlen(hint); buf_display_end = buf_display + ImStrlen(buf_display);
} }
else else
{ {
@ -5573,7 +5645,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 draw_scroll; ImVec2 draw_scroll;
// Render text. We currently only render selection when the widget is active or while scrolling. // Render text. We currently only render selection when the widget is active or while scrolling.
const ImU32 text_col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); const ImU32 text_col = GetColorU32(is_displaying_mixed ? ImGuiCol_TextMixedValue : is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
if (render_cursor || render_selection) if (render_cursor || render_selection)
{ {
// Render text (with cursor and selection) // Render text (with cursor and selection)
@ -5746,6 +5818,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (label_size.x > 0) if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
if (state && validated)
state->ValidatedThisFrame = true;
if (value_changed) if (value_changed)
MarkItemEdited(id); MarkItemEdited(id);
@ -6022,7 +6096,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
PushItemFlag(ImGuiItemFlags_MixedValue, false);
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
PopItemFlag();
} }
EndPopup(); EndPopup();
} }
@ -6136,6 +6212,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
const bool is_readonly = ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0; const bool is_readonly = ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
g.NextItemData.ClearFlags(); g.NextItemData.ClearFlags();
const float backup_alpha = g.Style.Alpha;
if (g.DisabledStackSize > 0)
g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
PushID(label); PushID(label);
const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0); const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0);
if (set_current_color_edit_id) if (set_current_color_edit_id)
@ -6293,6 +6373,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
if (!(flags & ImGuiColorEditFlags_NoSidePreview)) if (!(flags & ImGuiColorEditFlags_NoSidePreview))
{ {
PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
if ((flags & ImGuiColorEditFlags_NoLabel)) if ((flags & ImGuiColorEditFlags_NoLabel))
Text("Current"); Text("Current");
@ -6310,6 +6391,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
} }
} }
PopItemFlag(); PopItemFlag();
PopItemFlag();
EndGroup(); EndGroup();
} }
@ -6475,7 +6557,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{ {
float alpha = ImSaturate(col[3]); float alpha = ImSaturate(col[3]);
ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), style.Alpha, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size); float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size);
RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
@ -6493,6 +6575,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
g.ColorEditCurrentID = 0; g.ColorEditCurrentID = 0;
PopID(); PopID();
if (g.DisabledStackSize > 0)
g.Style.Alpha = backup_alpha;
return value_changed; return value_changed;
} }
@ -6525,34 +6610,42 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (flags & ImGuiColorEditFlags_InputHSV) if (flags & ImGuiColorEditFlags_InputHSV)
ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z); ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f); const ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
float grid_step = ImMin(size.x, size.y) / 2.99f; const float grid_step = ImMin(size.x, size.y) / 2.99f;
float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); const float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
ImRect bb_inner = bb; const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
float off = 0.0f;
if ((flags & ImGuiColorEditFlags_NoBorder) == 0) const float backup_alpha = g.Style.Alpha;
if (g.DisabledStackSize > 0)
g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
if (is_mixed)
{ {
off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding);
bb_inner.Expand(off); PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
if (g.MixedValueLabel != NULL)
RenderTextClipped(ImVec2(bb.Min.x, bb.Min.y + g.Style.FramePadding.y), bb.Max, g.MixedValueLabel, NULL, NULL, ImVec2(0.5f, 0.0f));
PopStyleColor();
} }
if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) else if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
{ {
float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); float mid_x = IM_ROUND((bb.Min.x + bb.Max.x) * 0.5f);
if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0) if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight); RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, ColorConvertFloat4ToU32(col_rgb), g.Style.Alpha, grid_step, ImVec2(-grid_step, 0.0f), rounding, ImDrawFlags_RoundCornersRight);
else else
window->DrawList->AddRectFilled(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundCornersRight); window->DrawList->AddRectFilled(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundCornersRight);
window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft); window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft);
} }
else else
{ {
// Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaOpaque) ? col_rgb_without_alpha : col_rgb; ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaOpaque) ? col_rgb_without_alpha : col_rgb;
if (col_source.w < 1.0f && (flags & ImGuiColorEditFlags_AlphaNoBg) == 0) if (col_source.w < 1.0f && (flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); RenderColorRectWithAlphaCheckerboard(window->DrawList, bb.Min, bb.Max, ColorConvertFloat4ToU32(col_source), g.Style.Alpha, grid_step, ImVec2(0.0f, 0.0f), rounding);
else else
window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(col_source), rounding);
} }
if (g.DisabledStackSize > 0)
g.Style.Alpha = backup_alpha;
RenderNavCursor(bb, id); RenderNavCursor(bb, id);
if ((flags & ImGuiColorEditFlags_NoBorder) == 0) if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
{ {
@ -6570,7 +6663,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once); SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
else else
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once); SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ColorButton(desc_id, col, flags); ColorButton(desc_id, col, flags);
PopItemFlag();
SameLine(); SameLine();
TextEx("Color"); TextEx("Color");
EndDragDropSource(); EndDragDropSource();
@ -6614,7 +6709,9 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_; ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_;
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz); ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz);
PopItemFlag();
SameLine(); SameLine();
if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_)) if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_))
{ {
@ -6896,7 +6993,7 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
} }
// Store ImGuiTreeNodeStackData for just submitted node. // Store ImGuiTreeNodeStackData for just submitted node.
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase. // Currently only supports 32 level deep. Easy to increase to e.g. 64.
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1) static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -6919,6 +7016,9 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth); window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth);
} }
#define TREE_NODE_MAX_DEPTH 32
#define TREE_NODE_GET_DEPTH_MASK(_DEPTH) (((ImU32)(_DEPTH) < TREE_NODE_MAX_DEPTH) ? (1u << (_DEPTH)) : 0u)
bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -6995,7 +7095,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0) if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0)
flags |= g.Style.TreeLinesFlags; flags |= g.Style.TreeLinesFlags;
const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f); const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f);
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen) && window->DC.TreeDepth < TREE_NODE_MAX_DEPTH)
{ {
store_tree_node_stack_data = draw_tree_lines; store_tree_node_stack_data = draw_tree_lines;
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsToParent) && !g.NavIdIsAlive) if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsToParent) && !g.NavIdIsAlive)
@ -7006,12 +7106,16 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
if (!is_visible) if (!is_visible)
{ {
if ((flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeRecordsClippedNodesY2Mask & (1 << (window->DC.TreeDepth - 1)))) if (flags & ImGuiTreeNodeFlags_DrawLinesToNodes)
{
const ImU32 tree_depth_mask = TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth - 1);
if (window->DC.TreeRecordsClippedNodesY2Mask & tree_depth_mask)
{ {
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway. parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
if (frame_bb.Min.y >= window->ClipRect.Max.y) if (frame_bb.Min.y >= window->ClipRect.Max.y)
window->DC.TreeRecordsClippedNodesY2Mask &= ~(1 << (window->DC.TreeDepth - 1)); // Done window->DC.TreeRecordsClippedNodesY2Mask &= ~tree_depth_mask; // Done
}
} }
if (is_open && store_tree_node_stack_data) if (is_open && store_tree_node_stack_data)
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID() TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
@ -7208,7 +7312,7 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (window->DC.TreeDepth == 0 || (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0) if ((window->DC.TreeHasStackDataDepthMask & TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth - 1)) == 0)
return; return;
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
@ -7292,8 +7396,7 @@ void ImGui::TreePop()
Unindent(); Unindent();
window->DC.TreeDepth--; window->DC.TreeDepth--;
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); ImU32 tree_depth_mask = TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth);
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask)
{ {
const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
@ -7520,7 +7623,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
// - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope()) // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
// - (2) usage will fail with clipped items // - (2) usage will fail with clipped items
// The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API. // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId) if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId && !g.NavJustMovedToIsInit)
if (g.NavJustMovedToId == id && (g.NavJustMovedToKeyMods & ImGuiMod_Ctrl) == 0) if (g.NavJustMovedToId == id && (g.NavJustMovedToKeyMods & ImGuiMod_Ctrl) == 0)
selected = pressed = auto_selected = true; selected = pressed = auto_selected = true;
} }
@ -10132,16 +10235,17 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
} }
// Horizontal scrolling buttons // Horizontal scrolling buttons
// Important: note that TabBarScrollButtons() will alter BarRect.Max.x. // - Important: note that TabBarScrollButtons() will alter BarRect.Max.x.
// - Selection skips buttons and might cross through sections if there are Tabs in Leading/Trailing sections.
const bool can_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) || (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyMixed); const bool can_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) || (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyMixed);
const float width_all_tabs_to_use_for_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) ? tab_bar->WidthAllTabs : width_all_tabs_after_min_width_shrink; const float width_all_tabs_to_use_for_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) ? tab_bar->WidthAllTabs : width_all_tabs_after_min_width_shrink;
tab_bar->ScrollButtonEnabled = ((width_all_tabs_to_use_for_scroll > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && can_scroll); tab_bar->ScrollButtonEnabled = ((width_all_tabs_to_use_for_scroll > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && can_scroll);
if (tab_bar->ScrollButtonEnabled) if (tab_bar->ScrollButtonEnabled)
if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar)) if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar))
{ {
scroll_to_tab_id = scroll_and_select_tab->ID;
if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0) if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0)
tab_bar->SelectedTabId = scroll_to_tab_id; tab_bar->SelectedTabId = scroll_and_select_tab->ID;
scroll_to_tab_id = scroll_and_select_tab->ID;
} }
if (scroll_to_tab_id == 0 && scroll_to_selected_tab) if (scroll_to_tab_id == 0 && scroll_to_selected_tab)
scroll_to_tab_id = tab_bar->SelectedTabId; scroll_to_tab_id = tab_bar->SelectedTabId;
@ -10334,6 +10438,14 @@ const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
return tab_bar->TabsNames.Buf.Data + tab->NameOffset; return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
} }
ImVec2 ImGui::TabBarGetTabPos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
if ((tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0)
return tab_bar->BarRect.Min + ImVec2(IM_TRUNC(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
else
return tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
}
// The purpose of this call is to register tab in advance so we can control their order at the time they appear. // The purpose of this call is to register tab in advance so we can control their order at the time they appear.
// Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function. // Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window) void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window)
@ -10402,11 +10514,20 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id); ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
if (tab == NULL) if (tab == NULL)
return; return;
// Clamp attempt to scroll to leading/trailing sections items.
// This could be done at the TabBarScrollingButtons() call site as well, but here works.
if (tab->Flags & ImGuiTabItemFlags_Leading)
tab = &tab_bar->Tabs[sections[0].TabCount];
else if (tab->Flags & ImGuiTabItemFlags_Trailing)
tab = &tab_bar->Tabs[sections[0].TabCount + sections[1].TabCount];
if (tab->Flags & ImGuiTabItemFlags_SectionMask_) if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
return; return;
// When scrolling to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
// Disable the margin if the scrolling section is too small for the target tab: prefer displaying a maximum of the label.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar) float margin = ImClamp(tab_bar->ScrollingRectMaxX - tab_bar->ScrollingRectMinX - tab->Width, g.Style.ItemInnerSpacing.x, g.FontSize * 1.0f);
int order = TabBarGetTabOrder(tab_bar, tab); int order = TabBarGetTabOrder(tab_bar, tab);
// Scrolling happens only in the central section (leading/trailing sections are not scrolling) // Scrolling happens only in the central section (leading/trailing sections are not scrolling)
@ -10811,10 +10932,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Layout // Layout
const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0; const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
size.x = tab->Width; size.x = tab->Width;
if (is_central_section) window->DC.CursorPos = TabBarGetTabPos(tab_bar, tab);
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_TRUNC(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
else
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);

View File

@ -1,12 +1,14 @@
HELPER FILES FOR POPULAR DEBUGGERS -----------------------------------------------------------------------------
HELPER FILES FOR POPULAR DEBUGGERS
-----------------------------------------------------------------------------
imgui.gdb imgui.gdb
GDB: disable stepping into trivial functions. GDB: disable stepping into trivial functions (*1).
(read comments inside file for details) (read comments inside file for details)
imgui.natstepfilter imgui.natstepfilter
Visual Studio Debugger: disable stepping into trivial functions. Visual Studio Debugger: disable stepping into trivial functions (*1).
(read comments inside file for details) (read comments inside file for details)
imgui.natvis imgui.natvis
@ -15,7 +17,23 @@ imgui.natvis
(read comments inside file for details) (read comments inside file for details)
imgui_lldb.py imgui_lldb.py
LLDB-based debuggers (*): synthetic children provider and summaries for Dear ImGui types. LLDB-based debuggers (*2): synthetic children provider and summaries for Dear ImGui types.
With this, types like ImVector<> will be displayed nicely in the debugger. With this, types like ImVector<> will be displayed nicely in the debugger.
(read comments inside file for details) (read comments inside file for details)
(*) Xcode, Android Studio, may be used from VS Code, C++Builder, CLion, Eclipse etc. (*2) Xcode, Android Studio, may be used from VS Code, C++Builder, CLion, Eclipse etc.
-----------------------------------------------------------------------------
NEW! DISABLED STEPPING INTO TRIVIAL FUNCTIONS
-----------------------------------------------------------------------------
Since 1.93.0 WIP (September 2026),
Dear ImGui uses a IM_NODEBUGSTEP macro to tag functions with __declspec(non_user_code)
or [[gnu::artificial]] to automatically tell debuggers to skip them.
(*1) Assuming the new IM_NODEBUGSTEP macro works, using imgui.natstepfilter etc.
may become unnecessary. Exact side effects on user experience yet to be clarified.
Additional references:
https://maskray.me/blog/skipping-boring-functions-in-debuggers
and https://news.ycombinator.com/item?id=42547576

View File

@ -9,4 +9,5 @@
# * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory # * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory
# Disable stepping into trivial functions # Disable stepping into trivial functions
# ...since Dear ImGui 1.93.0 WIP (September 2026): we use a IM_NODEBUGSTEP() macro to provide the equivalent feature via [[gnu::artificial]].
skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+ skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+

View File

@ -14,6 +14,8 @@ If you have multiple VS version installed, the version that matters is the one y
of (not the compiling toolset). This is supported since Visual Studio 2012. of (not the compiling toolset). This is supported since Visual Studio 2012.
More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2019#BKMK_C___Just_My_Code More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2019#BKMK_C___Just_My_Code
Since Dear ImGui 1.93.0 WIP (September 2026): we use a IM_NODEBUGSTEP() macro to provide the equivalent feature via __declspec(non_user_code).
--> -->
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010"> <StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">

View File

@ -1,14 +1,14 @@
// dear imgui: single-file wrapper include // dear imgui: single-file wrapper include
// We use this to validate compiling all *.cpp files in a same compilation unit. // We use this to validate compiling all *.cpp files in a same compilation unit.
// Users of that technique (also called "Unity builds") can generally provide this themselves, // Users of that technique (also called "Unity builds") can generally provide this themselves easily.
// so we don't really recommend you use this in your projects.
// Do this: // Do this:
// #define IMGUI_IMPLEMENTATION // #define IMGUI_IMPLEMENTATION
// Before you include this file in *one* C++ file to create the implementation. // #include "imgui_single_file.h"
// In *one* C++ file to create the implementation.
// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit. // Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit.
#ifdef IMGUI_IMPLEMENTATION #if defined(IMGUI_IMPLEMENTATION) && !defined(IMGUI_DEFINE_MATH_OPERATORS)
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
#endif #endif