diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index c00b2b493..1954be6dd 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -75,7 +75,7 @@ struct ImGui_ImplDX10_Data ID3D10InputLayout* pInputLayout; ID3D10Buffer* pVertexConstantBuffer; ID3D10PixelShader* pPixelShader; - ID3D10SamplerState* pFontSampler; + ID3D10SamplerState* pTexSamplerLinear; ID3D10RasterizerState* pRasterizerState; ID3D10BlendState* pBlendState; ID3D10DepthStencilState* pDepthStencilState; @@ -146,7 +146,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* device->VSSetShader(bd->pVertexShader); device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); device->PSSetShader(bd->pPixelShader); - device->PSSetSamplers(0, 1, &bd->pFontSampler); + device->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); device->GSSetShader(nullptr); // Setup render state @@ -263,7 +263,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplDX10_RenderState render_state; render_state.Device = bd->pd3dDevice; - render_state.SamplerDefault = bd->pFontSampler; + render_state.SamplerDefault = bd->pTexSamplerLinear; render_state.VertexConstantBuffer = bd->pVertexConstantBuffer; platform_io.Renderer_RenderState = &render_state; @@ -569,7 +569,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects() desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; desc.MinLOD = 0.f; desc.MaxLOD = 0.f; - bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); + bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear); } return true; @@ -585,7 +585,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects() for (ImTextureData* tex : ImGui::GetPlatformIO().Textures) if (tex->RefCount == 1) ImGui_ImplDX10_DestroyTexture(tex); - if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } + if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; } if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 95aa0c02d..9e6932e66 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -79,7 +79,7 @@ struct ImGui_ImplDX11_Data ID3D11InputLayout* pInputLayout; ID3D11Buffer* pVertexConstantBuffer; ID3D11PixelShader* pPixelShader; - ID3D11SamplerState* pFontSampler; + ID3D11SamplerState* pTexSamplerLinear; ID3D11RasterizerState* pRasterizerState; ID3D11BlendState* pBlendState; ID3D11DepthStencilState* pDepthStencilState; @@ -107,7 +107,7 @@ static void ImGui_ImplDX11_InitMultiViewportSupport(); static void ImGui_ImplDX11_ShutdownMultiViewportSupport(); // Functions -static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx) +static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx) { ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); @@ -151,7 +151,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0); device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0); - device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler); + device_ctx->PSSetSamplers(0, 1, &bd->pTexSamplerLinear); device_ctx->GSSetShader(nullptr, nullptr, 0); device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. @@ -279,7 +279,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ImGui_ImplDX11_RenderState render_state; render_state.Device = bd->pd3dDevice; render_state.DeviceContext = bd->pd3dDeviceContext; - render_state.SamplerDefault = bd->pFontSampler; + render_state.SamplerDefault = bd->pTexSamplerLinear; render_state.VertexConstantBuffer = bd->pVertexConstantBuffer; platform_io.Renderer_RenderState = &render_state; @@ -586,7 +586,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects() desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.MinLOD = 0.f; desc.MaxLOD = 0.f; - bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); + bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear); } return true; @@ -603,7 +603,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() if (tex->RefCount == 1) ImGui_ImplDX11_DestroyTexture(tex); - if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } + if (bd->pTexSamplerLinear) { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; } if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index cf9c39131..776a7b01f 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -98,7 +98,10 @@ struct ImGui_ImplDX12_Data DXGI_FORMAT DSVFormat; ID3D12DescriptorHeap* pd3dSrvDescHeap; UINT numFramesInFlight; - ImGui_ImplDX12_Texture FontTexture; + + ImGui_ImplDX12_RenderBuffers* pFrameResources; + UINT frameIndex; + bool LegacySingleDescriptorUsed; ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); } @@ -655,26 +658,26 @@ bool ImGui_ImplDX12_CreateDeviceObjects() param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling. - D3D12_STATIC_SAMPLER_DESC staticSampler = {}; - staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; - staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - staticSampler.MipLODBias = 0.f; - staticSampler.MaxAnisotropy = 0; - staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; - staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; - staticSampler.MinLOD = 0.f; - staticSampler.MaxLOD = D3D12_FLOAT32_MAX; - staticSampler.ShaderRegister = 0; - staticSampler.RegisterSpace = 0; - staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + D3D12_STATIC_SAMPLER_DESC staticSampler[1] = {}; + staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + staticSampler[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + staticSampler[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + staticSampler[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + staticSampler[0].MipLODBias = 0.f; + staticSampler[0].MaxAnisotropy = 0; + staticSampler[0].ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + staticSampler[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + staticSampler[0].MinLOD = 0.f; + staticSampler[0].MaxLOD = D3D12_FLOAT32_MAX; + staticSampler[0].ShaderRegister = 0; + staticSampler[0].RegisterSpace = 0; + staticSampler[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; D3D12_ROOT_SIGNATURE_DESC desc = {}; desc.NumParameters = _countof(param); desc.pParameters = param; desc.NumStaticSamplers = 1; - desc.pStaticSamplers = &staticSampler; + desc.pStaticSamplers = &staticSampler[0]; desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 6e89b4c45..3e8c65eb9 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -248,6 +248,7 @@ struct ImGui_ImplOpenGL3_Data GLsizeiptr VertexBufferSize; GLsizeiptr IndexBufferSize; bool HasPolygonMode; + bool HasBindSampler; bool HasClipOrigin; bool UseBufferSubData; ImVector TempBuffer; @@ -403,6 +404,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // Detect extensions we support #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3); +#endif +#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER + bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3); #endif bd->HasClipOrigin = (bd->GlVersion >= 450); #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS @@ -505,7 +509,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER - if (bd->GlVersion >= 330 || bd->GlProfileIsES3) + if (bd->HasBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise. #endif @@ -553,7 +557,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER - GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } + GLuint last_sampler; if (bd->HasBindSampler) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } #endif GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY @@ -678,7 +682,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER - if (bd->GlVersion >= 330 || bd->GlProfileIsES3) + if (bd->HasBindSampler) glBindSampler(0, last_sampler); #endif glActiveTexture(last_active_texture); diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index c3f5a93f5..a69ac89d7 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -180,6 +180,7 @@ typedef khronos_uint8_t GLubyte; #define GL_RENDERER 0x1F01 #define GL_VERSION 0x1F02 #define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 #define GL_LINEAR 0x2601 #define GL_TEXTURE_MAG_FILTER 0x2800 #define GL_TEXTURE_MIN_FILTER 0x2801 @@ -400,9 +401,15 @@ GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum #ifndef GL_VERSION_3_3 #define GL_VERSION_3_3 1 #define GL_SAMPLER_BINDING 0x8919 +typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); #ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); #endif #endif /* GL_VERSION_3_3 */ #ifndef GL_VERSION_4_1 @@ -483,7 +490,7 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc); /* gl3w internal state */ union ImGL3WProcs { - GL3WglProc ptr[60]; + GL3WglProc ptr[63]; struct { PFNGLACTIVETEXTUREPROC ActiveTexture; PFNGLATTACHSHADERPROC AttachShader; @@ -503,6 +510,7 @@ union ImGL3WProcs { PFNGLCREATESHADERPROC CreateShader; PFNGLDELETEBUFFERSPROC DeleteBuffers; PFNGLDELETEPROGRAMPROC DeleteProgram; + PFNGLDELETESAMPLERSPROC DeleteSamplers; PFNGLDELETESHADERPROC DeleteShader; PFNGLDELETETEXTURESPROC DeleteTextures; PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays; @@ -515,6 +523,7 @@ union ImGL3WProcs { PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; PFNGLFLUSHPROC Flush; PFNGLGENBUFFERSPROC GenBuffers; + PFNGLGENSAMPLERSPROC GenSamplers; PFNGLGENTEXTURESPROC GenTextures; PFNGLGENVERTEXARRAYSPROC GenVertexArrays; PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; @@ -535,6 +544,7 @@ union ImGL3WProcs { PFNGLPIXELSTOREIPROC PixelStorei; PFNGLPOLYGONMODEPROC PolygonMode; PFNGLREADPIXELSPROC ReadPixels; + PFNGLSAMPLERPARAMETERIPROC SamplerParameteri; PFNGLSCISSORPROC Scissor; PFNGLSHADERSOURCEPROC ShaderSource; PFNGLTEXIMAGE2DPROC TexImage2D; @@ -569,6 +579,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs; #define glCreateShader imgl3wProcs.gl.CreateShader #define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers #define glDeleteProgram imgl3wProcs.gl.DeleteProgram +#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers #define glDeleteShader imgl3wProcs.gl.DeleteShader #define glDeleteTextures imgl3wProcs.gl.DeleteTextures #define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays @@ -581,6 +592,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs; #define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray #define glFlush imgl3wProcs.gl.Flush #define glGenBuffers imgl3wProcs.gl.GenBuffers +#define glGenSamplers imgl3wProcs.gl.GenSamplers #define glGenTextures imgl3wProcs.gl.GenTextures #define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays #define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation @@ -601,6 +613,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs; #define glPixelStorei imgl3wProcs.gl.PixelStorei #define glPolygonMode imgl3wProcs.gl.PolygonMode #define glReadPixels imgl3wProcs.gl.ReadPixels +#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri #define glScissor imgl3wProcs.gl.Scissor #define glShaderSource imgl3wProcs.gl.ShaderSource #define glTexImage2D imgl3wProcs.gl.TexImage2D @@ -870,6 +883,7 @@ static const char *proc_names[] = { "glCreateShader", "glDeleteBuffers", "glDeleteProgram", + "glDeleteSamplers", "glDeleteShader", "glDeleteTextures", "glDeleteVertexArrays", @@ -882,6 +896,7 @@ static const char *proc_names[] = { "glEnableVertexAttribArray", "glFlush", "glGenBuffers", + "glGenSamplers", "glGenTextures", "glGenVertexArrays", "glGetAttribLocation", @@ -902,6 +917,7 @@ static const char *proc_names[] = { "glPixelStorei", "glPolygonMode", "glReadPixels", + "glSamplerParameteri", "glScissor", "glShaderSource", "glTexImage2D", diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 209f884a8..319cc747b 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -61,7 +61,7 @@ struct ImGui_ImplSDLGPU3_Data SDL_GPUShader* VertexShader = nullptr; SDL_GPUShader* FragmentShader = nullptr; SDL_GPUGraphicsPipeline* Pipeline = nullptr; - SDL_GPUSampler* TexSampler = nullptr; + SDL_GPUSampler* TexSamplerLinear = nullptr; SDL_GPUTransferBuffer* TexTransferBuffer = nullptr; uint32_t TexTransferBufferSize = 0; @@ -87,7 +87,7 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData() static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - render_state->SamplerCurrent = bd->TexSampler; + render_state->SamplerCurrent = bd->TexSamplerLinear; // Bind graphics pipeline SDL_BindGPUGraphicsPipeline(render_pass, pipeline); @@ -236,7 +236,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGui_ImplSDLGPU3_RenderState render_state; render_state.Device = bd->InitInfo.Device; - render_state.SamplerDefault = render_state.SamplerCurrent = bd->TexSampler; + render_state.SamplerDefault = render_state.SamplerCurrent = bd->TexSamplerLinear; platform_io.Renderer_RenderState = &render_state; ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height); @@ -341,7 +341,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex) texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1; SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info); - IM_ASSERT(raw_tex != nullptr && "Failed to create font texture, call SDL_GetError() for more info"); + IM_ASSERT(raw_tex != nullptr && "Failed to create texture, call SDL_GetError() for more info"); // Store identifiers tex->SetTexID((ImTextureID)(intptr_t)raw_tex); @@ -371,7 +371,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex) transferbuffer_info.size = upload_size + 1024; bd->TexTransferBufferSize = upload_size + 1024; bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info); - IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information"); + IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create transfer buffer, call SDL_GetError() for more information"); } // Copy to transfer buffer @@ -560,7 +560,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects() ImGui_ImplSDLGPU3_DestroyDeviceObjects(); - if (bd->TexSampler == nullptr) + if (bd->TexSamplerLinear == nullptr) { // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling. SDL_GPUSamplerCreateInfo sampler_info = {}; @@ -577,8 +577,8 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects() sampler_info.max_anisotropy = 1.0f; sampler_info.enable_compare = false; - bd->TexSampler = SDL_CreateGPUSampler(v->Device, &sampler_info); - IM_ASSERT(bd->TexSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information"); + bd->TexSamplerLinear = SDL_CreateGPUSampler(v->Device, &sampler_info); + IM_ASSERT(bd->TexSamplerLinear != nullptr && "Failed to create sampler, call SDL_GetError() for more information"); } ImGui_ImplSDLGPU3_CreateGraphicsPipeline(); @@ -613,7 +613,7 @@ void ImGui_ImplSDLGPU3_DestroyDeviceObjects() if (bd->TexTransferBuffer) { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; } if (bd->VertexShader) { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; } if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; } - if (bd->TexSampler) { SDL_ReleaseGPUSampler(v->Device, bd->TexSampler); bd->TexSampler = nullptr; } + if (bd->TexSamplerLinear) { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerLinear); bd->TexSamplerLinear = nullptr; } if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; } } @@ -663,7 +663,7 @@ void ImGui_ImplSDLGPU3_NewFrame() ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?"); - if (!bd->TexSampler) + if (!bd->TexSamplerLinear) ImGui_ImplSDLGPU3_CreateDeviceObjects(); } diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 96ebbe890..d2554a402 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -283,7 +283,7 @@ struct ImGui_ImplVulkan_Data ImVector PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array // Texture management - VkSampler TexSampler; + VkSampler TexSamplerLinear; VkCommandPool TexCommandPool; VkCommandBuffer TexCommandBuffer; @@ -766,7 +766,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex) } // Create the Descriptor Set - backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSamplerLinear, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // Store identifiers tex->SetTexID((ImTextureID)backend_tex->DescriptorSet); @@ -1066,7 +1066,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; VkResult err; - if (!bd->TexSampler) + if (!bd->TexSamplerLinear) { // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling. VkSamplerCreateInfo info = {}; @@ -1080,7 +1080,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() info.minLod = -1000; info.maxLod = 1000; info.maxAnisotropy = 1.0f; - err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSampler); + err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSamplerLinear); check_vk_result(err); } @@ -1217,7 +1217,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() if (bd->TexCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; } if (bd->TexCommandPool) { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; } - if (bd->TexSampler) { vkDestroySampler(v->Device, bd->TexSampler, v->Allocator); bd->TexSampler = VK_NULL_HANDLE; } + if (bd->TexSamplerLinear) { vkDestroySampler(v->Device, bd->TexSamplerLinear, v->Allocator); bd->TexSamplerLinear = VK_NULL_HANDLE; } if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; } if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; } if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f89921cf2..f488b79c3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,14 +69,24 @@ Other Changes: - InputText: revert a change in 1.79 where pressing Down or PageDown on the last line of a multi-line buffer without a trailing carriage return would keep the cursor unmoved. We revert back to move to the end of line in this situation. +- Focus, InputText: fixed an issue where SetKeyboardFocusHere() did not work + on InputTextMultiline() fields with ImGuiInputTextFlags_AllowTabInput, since + they normally inhibit activation to allow tabbing through multiple items. (#8928) +- Selectable: added ImGuiSelectableFlags_SelectOnNav to auto-select an item when + moved into (automatic when in a BeginMultiSelect() block). +- TabBar: fixed an issue were forcefully selecting a tab using internal API would + be ignored on first/appearing frame before tabs are submitted (#8929, #6681) - DrawList: fixed CloneOutput() unnecessarily taking a copy of the ImDrawListSharedData pointer, which could to issue when deleting the cloned list. (#8894, #1860) +- DrawList: made AddCallback() assert when passing a null callback. - Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers from being displayed in the tool. (#8905, #4631) - Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ### is now skipped. (#8904, #4631) - Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in output path. (#8904, #4631) +- Demo: tweaked ShowFontSelector() and ShowStyleSelector() to update selection + while navigating and to not close popup automatically. - Examples: Android: Android+OpenGL3: update Gradle project (#8888, #8878) [@scribam] - Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and PresentMode to configure how secondary viewports are created. Currently only used diff --git a/imgui.cpp b/imgui.cpp index 275ca0a96..16903c27a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14638,6 +14638,8 @@ void ImGui::NavMoveRequestApplyResult() { g.NavNextActivateId = result->ID; g.NavNextActivateFlags = ImGuiActivateFlags_None; + if (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) + g.NavNextActivateFlags |= ImGuiActivateFlags_FromFocusApi; if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing; } @@ -21403,6 +21405,7 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImG // - DebugNodeWindowSettings() [Internal] // - DebugNodeWindowsList() [Internal] // - DebugNodeWindowsListByBeginStackParent() [Internal] +// - ShowFontSelector() //----------------------------------------------------------------------------- #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS) @@ -23749,7 +23752,7 @@ void ImGui::ShowFontSelector(const char* label) for (ImFont* font : io.Fonts->Fonts) { PushID((void*)font); - if (Selectable(font->GetDebugName(), font == font_current)) + if (Selectable(font->GetDebugName(), font == font_current, ImGuiSelectableFlags_SelectOnNav | ImGuiSelectableFlags_NoAutoClosePopups)) io.FontDefault = font; if (font == font_current) SetItemDefaultFocus(); diff --git a/imgui.h b/imgui.h index 4f34d60de..253904784 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.3 WIP" -#define IMGUI_VERSION_NUM 19226 +#define IMGUI_VERSION_NUM 19227 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 #define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. @@ -1380,6 +1380,7 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered + ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into. Automatic when in a BeginMultiSelect() block. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b20039418..20f494ef5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8333,17 +8333,25 @@ void ImGui::ShowAboutWindow(bool* p_open) bool ImGui::ShowStyleSelector(const char* label) { static int style_idx = -1; - if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0")) + const char* style_names[] = { "Dark", "Light", "Classic" }; + bool ret = false; + if (ImGui::BeginCombo(label, (style_idx >= 0 && style_idx < IM_ARRAYSIZE(style_names)) ? style_names[style_idx] : "")) { - switch (style_idx) - { - case 0: ImGui::StyleColorsDark(); break; - case 1: ImGui::StyleColorsLight(); break; - case 2: ImGui::StyleColorsClassic(); break; - } - return true; + for (int n = 0; n < IM_ARRAYSIZE(style_names); n++) + if (ImGui::Selectable(style_names[n], style_idx == n, ImGuiSelectableFlags_SelectOnNav | ImGuiSelectableFlags_NoAutoClosePopups)) + { + style_idx = n; + ret = true; + switch (style_idx) + { + case 0: ImGui::StyleColorsDark(); break; + case 1: ImGui::StyleColorsLight(); break; + case 2: ImGui::StyleColorsClassic(); break; + } + } + ImGui::EndCombo(); } - return false; + return ret; } static const char* GetTreeLinesFlagsName(ImGuiTreeNodeFlags flags) @@ -9395,10 +9403,9 @@ static void ShowExampleAppLayout(bool* p_open) ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX); for (int i = 0; i < 100; i++) { - // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav char label[128]; sprintf(label, "MyObject %d", i); - if (ImGui::Selectable(label, selected == i)) + if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SelectOnNav)) selected = i; } ImGui::EndChild(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 901566847..5f37481d1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -524,6 +524,7 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t use { IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; + IM_ASSERT(callback != NULL); IM_ASSERT(curr_cmd->UserCallback == NULL); if (curr_cmd->ElemCount != 0) { diff --git a/imgui_internal.h b/imgui_internal.h index 422b7d2e7..b33954a6c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1086,7 +1086,6 @@ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, - ImGuiSelectableFlags_SelectOnNav = 1 << 21, // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API. ImGuiSelectableFlags_SelectOnClick = 1 << 22, // Override button behavior to react on Click (default is Click+Release) ImGuiSelectableFlags_SelectOnRelease = 1 << 23, // Override button behavior to react on Release (default is Click+Release) ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) @@ -1702,8 +1701,9 @@ enum ImGuiActivateFlags_ ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key. ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) - ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request + ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request (ImGuiNavMoveFlags_IsTabbing) ImGuiActivateFlags_FromShortcut = 1 << 4, // Activation requested by an item shortcut via SetNextItemShortcut() function. + ImGuiActivateFlags_FromFocusApi = 1 << 5, // Activation requested by an api request (ImGuiNavMoveFlags_FocusApi) }; // Early work-in-progress API for ScrollToItem() @@ -3815,6 +3815,8 @@ namespace ImGui // Tab Bars inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; } + IMGUI_API ImGuiTabBar* TabBarFindByID(ImGuiID id); + IMGUI_API void TabBarRemove(ImGuiTabBar* tab_bar); IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags); IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index ba8f0034f..5b4e3e07d 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3943,7 +3943,7 @@ void ImGui::TableSettingsAddSettingsHandler() // - TableGcCompactSettings() [Internal] //------------------------------------------------------------------------- -// Remove Table (currently only used by TestEngine) +// Remove Table data (currently only used by TestEngine) void ImGui::TableRemove(ImGuiTable* table) { //IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 094cefea2..2ae0fc393 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3998,7 +3998,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c namespace ImStb { static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; } -static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; } +static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx >= 0 && idx <= obj->TextLen); return obj->TextSrc[idx]; } static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontBakedScale; } static char STB_TEXTEDIT_NEWLINE = '\n'; static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx) @@ -4613,8 +4613,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; - // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping. - if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput)) + // Prevent NavActivation from explicit Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping. + if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && !(g.NavActivateFlags & ImGuiActivateFlags_FromFocusApi) && (flags & ImGuiInputTextFlags_AllowTabInput)) g.NavActivateId = 0; // Prevent NavActivate reactivating in BeginChild() when we are already active. @@ -7354,6 +7354,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); + bool auto_selected = false; // Multi-selection support (footer) if (is_multi_select) @@ -7371,7 +7372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // 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 (g.NavJustMovedToId == id) - selected = pressed = true; + selected = pressed = auto_selected = true; } // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with keyboard/gamepad @@ -7422,8 +7423,9 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb); // Automatically close popups - if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups)) - CloseCurrentPopup(); + if (pressed && !auto_selected && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups)) + if (!(flags & ImGuiSelectableFlags_SelectOnNav) || g.NavJustMovedToId != id) + CloseCurrentPopup(); if (disabled_item && !disabled_global) EndDisabled(); @@ -9568,6 +9570,19 @@ static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) return ImGuiPtrOrIndex(tab_bar); } +ImGuiTabBar* ImGui::TabBarFindByID(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + return g.TabBars.GetByKey(id); +} + +// Remove TabBar data (currently only used by TestEngine) +void ImGui::TabBarRemove(ImGuiTabBar* tab_bar) +{ + ImGuiContext& g = *GImGui; + g.TabBars.Remove(tab_bar->ID, tab_bar); +} + bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) { ImGuiContext& g = *GImGui; @@ -9907,7 +9922,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) tab_bar->TabsNames.Buf.resize(0); // If we have lost the selected tab, select the next most recently active one - if (found_selected_tab_id == false) + const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); + if (found_selected_tab_id == false && !tab_bar_appearing) tab_bar->SelectedTabId = 0; if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL) scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID; diff --git a/imstb_textedit.h b/imstb_textedit.h index 49c8933e2..844be3b2b 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -582,7 +582,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING STB_TEXTEDIT_LAYOUTROW(&r, str, i); if (n < i + r.num_chars) break; - if (str->LastMoveDirectionLR == ImGuiDir_Right && str->Stb->cursor == i + r.num_chars && STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] Wrapping point handling + if (str->LastMoveDirectionLR == ImGuiDir_Right && str->Stb->cursor > 0 && str->Stb->cursor == i + r.num_chars && STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] Wrapping point handling break; if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line break; // [DEAR IMGUI]