Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_dx10.cpp
#	backends/imgui_impl_dx10.h
#	backends/imgui_impl_dx11.cpp
#	backends/imgui_impl_dx11.h
#	backends/imgui_impl_dx12.cpp
#	backends/imgui_impl_dx12.h
#	backends/imgui_impl_opengl2.cpp
#	backends/imgui_impl_opengl3.cpp
#	backends/imgui_impl_opengl3.h
#	backends/imgui_impl_sdlgpu3.cpp
#	backends/imgui_impl_sdlgpu3.h
#	backends/imgui_impl_sdlrenderer3.cpp
#	backends/imgui_impl_sdlrenderer3.h
#	backends/imgui_impl_vulkan.cpp
#	backends/imgui_impl_vulkan.h
#	backends/imgui_impl_wgpu.cpp
#	backends/imgui_impl_wgpu.h
#	imgui.cpp
#	imgui_internal.h
#	imgui_widgets.cpp
This commit is contained in:
ocornut 2026-09-18 22:19:23 +02:00
commit 730623ea35
26 changed files with 366 additions and 177 deletions

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.

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.
@ -47,4 +48,6 @@ struct ImGui_ImplDX10_RenderState
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest) //ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
}; };
static inline ImGui_ImplDX10_RenderState* ImGui_ImplDX10_GetRenderState() { return (ImGui_ImplDX10_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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.

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.
@ -50,4 +50,6 @@ struct ImGui_ImplDX11_RenderState
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest) //ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
}; };
static inline ImGui_ImplDX11_RenderState* ImGui_ImplDX11_GetRenderState() { return (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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.

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.
@ -76,6 +76,8 @@ struct ImGui_ImplDX12_RenderState
ID3D12GraphicsCommandList* CommandList; ID3D12GraphicsCommandList* CommandList;
}; };
static inline ImGui_ImplDX12_RenderState* ImGui_ImplDX12_GetRenderState() { return (ImGui_ImplDX12_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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
// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap' // - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'

View File

@ -28,7 +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-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628) // 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)
@ -138,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!!),
@ -164,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.
@ -369,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,7 +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-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628) // 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)
@ -392,9 +394,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.
@ -417,16 +422,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);
} }
@ -434,26 +438,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.
@ -527,11 +535,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);
@ -1102,6 +1106,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,8 +74,8 @@ 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
}; };
static inline ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState() { return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; } static inline ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState() { return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }

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.

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.
@ -60,4 +61,6 @@ struct ImGui_ImplSDLGPU3_RenderState
SDL_GPUDevice* Device; SDL_GPUDevice* Device;
}; };
static inline ImGui_ImplSDLGPU3_RenderState* ImGui_ImplSDLGPU3_GetRenderState() { return (ImGui_ImplSDLGPU3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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

View File

@ -53,4 +53,6 @@ struct ImGui_ImplSDLRenderer2_RenderState
SDL_Renderer* Renderer; SDL_Renderer* Renderer;
}; };
static inline ImGui_ImplSDLRenderer2_RenderState* ImGui_ImplSDLRenderer2_GetRenderState() { return (ImGui_ImplSDLRenderer2_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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)); }
}; };
@ -80,14 +86,13 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
// 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 +122,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 +219,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 +261,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 +286,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 +368,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,9 @@ 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.
}; };
static inline ImGui_ImplSDLRenderer3_RenderState* ImGui_ImplSDLRenderer3_GetRenderState() { return (ImGui_ImplSDLRenderer3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
#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.

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.
@ -184,6 +184,8 @@ struct ImGui_ImplVulkan_RenderState
VkPipelineLayout PipelineLayout; VkPipelineLayout PipelineLayout;
}; };
static inline ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState() { return (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// 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.

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.
@ -84,6 +84,8 @@ struct ImGui_ImplWGPU_RenderState
WGPURenderPassEncoder RenderPassEncoder; WGPURenderPassEncoder RenderPassEncoder;
}; };
static inline ImGui_ImplWGPU_RenderState* ImGui_ImplWGPU_GetRenderState() { return (ImGui_ImplWGPU_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Internal Helpers // Internal Helpers
// Those are currently used by our example applications. // Those are currently used by our example applications.

View File

@ -45,6 +45,8 @@ Breaking Changes:
favor of `style.CurveTessellationMaxError` (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.CurveTessellationMaxError == 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
@ -60,6 +62,14 @@ Other Changes:
- TreeNode: - TreeNode:
- Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX - Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
features or other features requiring stack storage. (#9509) [@lasrod] 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
@ -73,6 +83,16 @@ Other Changes:
- Amended context menu right-click opening code to check that the right-click - 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 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) to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
- ImGuiTextFilter:
- Added support for space ' ' as separator, which is more standard. (#2435, #30)
- Added support for quoted "xxx" blocks to e.g. match words sequences. (#2435)
- 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: - Misc:
- Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values. - Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values.
Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX() Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX()
@ -87,19 +107,34 @@ Other Changes:
and various operators. and various operators.
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing - 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] issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
- ImDrawList: - 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 - 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 texture that was queue for destroy during the frame. Make it safe to stick to
an existing texture during the frame. (#9528, #8465) 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: - Demo:
- Added `Widgets->Mixed Values` section. (#5518, #5677, #6865) - 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] - 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]

152
imgui.cpp
View File

@ -402,6 +402,8 @@ 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/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. - 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). - 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:
@ -3154,11 +3156,13 @@ 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; FilterOp = '|';
MinWordSize = 1;
_CountExclude = _CountInclude = 0;
if (default_filter) if (default_filter)
{ {
ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf)); ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf));
@ -3166,85 +3170,93 @@ 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 items
{
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 = _CountInclude = 0;
input_range.split(',', &Filters); IM_ASSERT(FilterOp == '|' || FilterOp == '&');
const char* buf_e = InputBuf + ImStrlen(InputBuf);
CountGrep = 0; const char* word_e;
for (ImGuiTextRange& f : Filters) 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)
word_b++;
const bool is_quote = (word_b < buf_e && word_b[0] == '\"');
if (is_quote)
{
// Parsing quotes. Omit storing leading/trailing quotes.
word_e = ImStrchrRange(++word_b, buf_e, '\"');
if (word_e == NULL)
word_e = buf_e;
}
else
{
// Handle both ' ' and ',' separators.
for (word_e = word_b; word_e < buf_e; word_e++)
if (*word_e == ' ' || *word_e == ',')
break;
}
// Min length
if (word_e - word_b < MinWordSize)
continue; continue;
if (f.b[0] != '-')
CountGrep += 1; // Add to list
// The '-' is not stored in items but implicitly inferred using (n < CountExclude).
// FIXME-OPT: about ~push_front(): as N is derived from user inputs we expect this to be fine.
_Items.insert(is_excl ? _Items.Data : _Items.Data + _Items.Size, ImGuiTextFilter::ImGuiTextFilterItem(word_b, word_e));
if (is_excl)
_CountExclude++;
else
_CountInclude++;
} }
} }
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
{ {
if (Filters.Size == 0) if (_Items.Size == 0)
return true; return true;
if (text == NULL) if (text == NULL)
text = text_end = ""; text = text_end = "";
for (const ImGuiTextRange& f : Filters) // Filters are sorted so that '-' ones are always leading.
{ int n;
if (f.b == f.e) for (n = 0; n < _CountExclude; n++)
continue; if (ImStristr(text, text_end, _Items.Data[n].Begin, _Items.Data[n].End) != NULL)
if (f.b[0] == '-')
{
// Subtract
if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
return false; return false;
} const bool is_and_filter = (FilterOp == '&');
else for (; n < _Items.Size; n++)
{ {
// Grep const bool is_match = ImStristr(text, text_end, _Items.Data[n].Begin, _Items.Data[n].End) != NULL;
if (ImStristr(text, text_end, f.b, f.e) != NULL) if (is_match && !is_and_filter) // or incl 1 -> true
return true; return true; // or incl 0 -> continue
} if (!is_match && is_and_filter) // and incl 1 -> continue
return false; // and incl 0 -> false
} }
// Implicit * grep // When no inclusion are specified (only exclusions) we implicitly pass
if (CountGrep == 0) if (_CountInclude == 0)
return true; return true;
return is_and_filter;
return false;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -4420,7 +4432,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...
@ -14885,6 +14897,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;
} }
@ -15152,6 +15165,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);
} }
@ -16078,17 +16092,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)
@ -16119,6 +16125,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;
@ -16898,7 +16914,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()

42
imgui.h
View File

@ -2919,30 +2919,37 @@ 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 -ccc'.
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");
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); }
#endif
// [Internal] Don't use! Will be replaced with ImStrv.
struct ImGuiTextFilterItem
{ {
const char* b; const char* Begin;
const char* e; const char* End;
ImGuiTextFilterItem(const char* b, const char* e) { Begin = b; End = e; }
ImGuiTextRange() { b = e = NULL; }
ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; }
bool empty() const { return b == e; }
IMGUI_API void split(char separator, ImVector<ImGuiTextRange>* out) const;
}; };
char InputBuf[256];
ImVector<ImGuiTextRange>Filters; // [Internal] Members
int CountGrep; char InputBuf[256]; // User input buffer
char FilterOp; // == '|' (any) pr '&' (all)
ImU8 MinWordSize; // == 1
int _CountExclude; // >= 0
int _CountInclude; // >= 0
ImVector<ImGuiTextFilterItem> _Items; // Pre-parsed, trimmed, reordered items
}; };
// Helper: Growable text buffer for logging/accumulating text // Helper: Growable text buffer for logging/accumulating text
@ -4324,6 +4331,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

@ -1523,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++)
{ {
@ -3830,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))
@ -3849,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.
@ -4020,7 +4032,8 @@ static void DemoWindowWidgetsTextFilter()
" \"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\" or \"yyy\"\n"
" \"-xxx\" hide lines containing \"xxx\""); " \"-xxx\" hide lines containing \"xxx\"");
filter.Draw(); ImGui::SetNextItemWidth(-FLT_MIN);
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
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 (int i = 0; i < IM_COUNTOF(lines); i++)
if (filter.PassFilter(lines[i])) if (filter.PassFilter(lines[i]))
@ -8923,9 +8936,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();
@ -8935,6 +8945,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);
@ -9347,7 +9361,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
@ -9682,7 +9699,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();
@ -9877,7 +9895,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);

View File

@ -418,7 +418,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'); }
@ -2651,6 +2651,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)
@ -3588,7 +3589,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);
@ -3966,6 +3967,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
@ -3999,6 +4001,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);

View File

@ -3184,18 +3184,18 @@ 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)
{ {
const float mouse_abs_pos = g.IO.MousePos[axis]; const float mouse_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;
@ -7623,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;
} }
@ -10235,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;
@ -10437,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)
@ -10505,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)
@ -10914,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);