diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1a71b22c..fa210ba9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -100,6 +100,8 @@ Other changes: Breaking Changes: - ImDrawList: Fixed rectangles with thick lines (>1.0f) not being as thick as requested. (#2518) If you have custom rendering using thick lines, they will appear thicker now. +- Obsoleted GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. + Kept inline redirection function. - Examples: Vulkan: Added MinImageCount/ImageCount fields in ImGui_ImplVulkan_InitInfo, required during initialization to specify the number of in-flight image requested by swap chains. (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). (#2071, #1677) [@nathanvoglsam] @@ -107,6 +109,11 @@ Breaking Changes: on them but it is possible you have!). Other Changes: +- ImDrawList: Added ImDrawCallback_ResetRenderState, a special ImDrawList::AddCallback() value + to request the renderer back-end to reset its render state. (#2037, #1639, #2452) + Examples: Added support for ImDrawCallback_ResetRenderState in all renderer back-ends. Each + renderer code setting up initial render state has been moved to a function so it could be + called at the start of rendering and when a ResetRenderState is requested. [@ocornut, @bear24rw] - InputText: Fixed selection background starts rendering one frame after the cursor movement when first transitioning from no-selection to has-selection. (Bug in 1.69) (#2436) [@Nazg-Gul] - InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336) @@ -139,6 +146,8 @@ Other Changes: - Separator: Declare its thickness (1.0f) to the layout, making items around separator more symmetrical. - Combo, Slider, Scrollbar: Improve rendering in situation when there's only a few pixels available (<3 pixels). - Nav: Fixed Drag/Slider functions going into text input mode when keyboard CTRL is held while pressing NavActivate. +- Drag and Drop: Fixed drag source with ImGuiDragDropFlags_SourceAllowNullID and null ID from receiving click + regardless of being covered by another window (it didn't honor correct hovering rules). (#2521) - ImDrawList: Improved algorithm for mitre joints on thick lines, preserving correct thickness up to 90 degrees angles, also faster to output. (#2518) [@rmitton] - Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert diff --git a/docs/TODO.txt b/docs/TODO.txt index aedee9ce..79cdccd1 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -262,6 +262,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - filters: handle wild-cards (with implicit leading/trailing *), reg-exprs - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) + - drag and drop: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers. - drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725) - drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. - drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725) diff --git a/examples/imgui_impl_allegro5.cpp b/examples/imgui_impl_allegro5.cpp index ca0444ff..b05fa2a3 100644 --- a/examples/imgui_impl_allegro5.cpp +++ b/examples/imgui_impl_allegro5.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-04-30: Renderer: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-11-30: Platform: Added touchscreen support. // 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window. // 2018-06-13: Platform: Added clipboard support (from Allegro 5.1.12). @@ -60,23 +61,9 @@ struct ImDrawVertAllegro ALLEGRO_COLOR col; }; -// Render function. -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) +static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data) { - // Avoid rendering when minimized - if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) - return; - - // Backup Allegro state that will be modified - ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); - ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); - int last_clip_x, last_clip_y, last_clip_w, last_clip_h; - al_get_clipping_rectangle(&last_clip_x, &last_clip_y, &last_clip_w, &last_clip_h); - int last_blender_op, last_blender_src, last_blender_dst; - al_get_blender(&last_blender_op, &last_blender_src, &last_blender_dst); - - // Setup render state + // Setup blending al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); // Setup orthographic projection matrix @@ -92,7 +79,28 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) al_orthographic_transform(&transform, L, T, 1.0f, R, B, -1.0f); al_use_projection_transform(&transform); } +} + +// Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) +{ + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + + // Backup Allegro state that will be modified + ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); + ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); + int last_clip_x, last_clip_y, last_clip_w, last_clip_h; + al_get_clipping_rectangle(&last_clip_x, &last_clip_y, &last_clip_w, &last_clip_h); + int last_blender_op, last_blender_src, last_blender_dst; + al_get_blender(&last_blender_op, &last_blender_src, &last_blender_dst); + + // Setup desired render state + ImGui_ImplAllegro5_SetupRenderState(draw_data); + // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -135,10 +143,16 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplAllegro5_SetupRenderState(draw_data); + else + pcmd->UserCallback(cmd_list, pcmd); } else { + // Draw ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId; al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index 6c2075e6..94ae9339 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions. @@ -61,6 +62,37 @@ struct VERTEX_CONSTANT_BUFFER static void ImGui_ImplDX10_InitPlatformInterface(); static void ImGui_ImplDX10_ShutdownPlatformInterface(); +static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx) +{ + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)draw_data->DisplaySize.x; + vp.Height = (UINT)draw_data->DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); + + // Bind shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); + + // Setup render state + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); + ctx->RSSetState(g_pRasterizerState); +} + // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) @@ -178,33 +210,8 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); - // Setup viewport - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)draw_data->DisplaySize.x; - vp.Height = (UINT)draw_data->DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0; - ctx->RSSetViewports(1, &vp); - - // Bind shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - ctx->IASetInputLayout(g_pInputLayout); - ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->VSSetShader(g_pVertexShader); - ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - ctx->PSSetShader(g_pPixelShader); - ctx->PSSetSamplers(0, 1, &g_pFontSampler); - - // Setup render state - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); - ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); - ctx->RSSetState(g_pRasterizerState); + // Setup desired DX state + ImGui_ImplDX10_SetupRenderState(draw_data, ctx); // Render command lists int vtx_offset = 0; @@ -218,8 +225,12 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX10_SetupRenderState(draw_data, ctx); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 649e5e67..80ea9959 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. @@ -61,6 +62,38 @@ struct VERTEX_CONSTANT_BUFFER static void ImGui_ImplDX11_InitPlatformInterface(); static void ImGui_ImplDX11_ShutdownPlatformInterface(); +static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) +{ + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = draw_data->DisplaySize.x; + vp.Height = draw_data->DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); + + // Setup shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); + + // Setup blend state + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); + ctx->RSSetState(g_pRasterizerState); +} +>>>>>>> master + // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) @@ -183,33 +216,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); - // Setup viewport - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = draw_data->DisplaySize.x; - vp.Height = draw_data->DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0; - ctx->RSSetViewports(1, &vp); - - // Bind shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - ctx->IASetInputLayout(g_pInputLayout); - ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->VSSetShader(g_pVertexShader, NULL, 0); - ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - ctx->PSSetShader(g_pPixelShader, NULL, 0); - ctx->PSSetSamplers(0, 1, &g_pFontSampler); - - // Setup render state - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); - ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); - ctx->RSSetState(g_pRasterizerState); + // Setup desired DX state + ImGui_ImplDX11_SetupRenderState(draw_data, ctx); // Render command lists int vtx_offset = 0; @@ -221,10 +229,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != NULL) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX11_SetupRenderState(draw_data, ctx); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 92057496..6fa0ac96 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-04-30: DirectX12: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: Misc: Various minor tidying up. // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -62,6 +63,61 @@ struct VERTEX_CONSTANT_BUFFER static void ImGui_ImplDX12_InitPlatformInterface(); static void ImGui_ImplDX12_ShutdownPlatformInterface(); +static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) +{ + // Setup orthographic projection matrix into our constant buffer + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). + VERTEX_CONSTANT_BUFFER vertex_constant_buffer; + { + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp)); + } + + // Setup viewport + D3D12_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D12_VIEWPORT)); + vp.Width = draw_data->DisplaySize.x; + vp.Height = draw_data->DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); + + // Bind shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + D3D12_VERTEX_BUFFER_VIEW vbv; + memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW)); + vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset; + vbv.SizeInBytes = fr->VertexBufferSize * stride; + vbv.StrideInBytes = stride; + ctx->IASetVertexBuffers(0, 1, &vbv); + D3D12_INDEX_BUFFER_VIEW ibv; + memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW)); + ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress(); + ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx); + ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + ctx->IASetIndexBuffer(&ibv); + ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->SetPipelineState(g_pPipelineState); + ctx->SetGraphicsRootSignature(g_pRootSignature); + ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); + + // Setup blend factor + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendFactor(blend_factor); +} + // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) @@ -144,57 +200,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL fr->VertexBuffer->Unmap(0, &range); fr->IndexBuffer->Unmap(0, &range); - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. - VERTEX_CONSTANT_BUFFER vertex_constant_buffer; - { - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp)); - } - - // Setup viewport - D3D12_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D12_VIEWPORT)); - vp.Width = draw_data->DisplaySize.x; - vp.Height = draw_data->DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0.0f; - ctx->RSSetViewports(1, &vp); - - // Bind shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - D3D12_VERTEX_BUFFER_VIEW vbv; - memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW)); - vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset; - vbv.SizeInBytes = fr->VertexBufferSize * stride; - vbv.StrideInBytes = stride; - ctx->IASetVertexBuffers(0, 1, &vbv); - D3D12_INDEX_BUFFER_VIEW ibv; - memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW)); - ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress(); - ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx); - ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; - ctx->IASetIndexBuffer(&ibv); - ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->SetPipelineState(g_pPipelineState); - ctx->SetGraphicsRootSignature(g_pRootSignature); - ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); - - // Setup blend factor - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendFactor(blend_factor); + // Setup desired DX state + ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr); // Render command lists int vtx_offset = 0; @@ -206,10 +213,14 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != NULL) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_dx9.cpp b/examples/imgui_impl_dx9.cpp index fb71bbbb..628114b8 100644 --- a/examples/imgui_impl_dx9.cpp +++ b/examples/imgui_impl_dx9.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). // 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -48,6 +49,62 @@ struct CUSTOMVERTEX static void ImGui_ImplDX9_InitPlatformInterface(); static void ImGui_ImplDX9_ShutdownPlatformInterface(); +static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) +{ + // Setup viewport + D3DVIEWPORT9 vp; + vp.X = vp.Y = 0; + vp.Width = (DWORD)draw_data->DisplaySize.x; + vp.Height = (DWORD)draw_data->DisplaySize.y; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + g_pd3dDevice->SetViewport(&vp); + + // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) + g_pd3dDevice->SetPixelShader(NULL); + g_pd3dDevice->SetVertexShader(NULL); + g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); + g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); + g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); + g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + // Setup orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. + // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() + { + float L = draw_data->DisplayPos.x + 0.5f; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; + float T = draw_data->DisplayPos.y + 0.5f; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; + D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } }; + D3DMATRIX mat_projection = + { { { + 2.0f/(R-L), 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/(T-B), 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f + } } }; + g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); + } +} + // Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) @@ -117,58 +174,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) g_pd3dDevice->SetIndices(g_pIB); g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); - // Setup viewport - D3DVIEWPORT9 vp; - vp.X = vp.Y = 0; - vp.Width = (DWORD)draw_data->DisplaySize.x; - vp.Height = (DWORD)draw_data->DisplaySize.y; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - g_pd3dDevice->SetViewport(&vp); - - // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) - g_pd3dDevice->SetPixelShader(NULL); - g_pd3dDevice->SetVertexShader(NULL); - g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); - g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); - g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); - g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - - // Setup orthographic projection matrix - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. - // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() - { - float L = draw_data->DisplayPos.x + 0.5f; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; - float T = draw_data->DisplayPos.y + 0.5f; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; - D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } }; - D3DMATRIX mat_projection = - { { { - 2.0f/(R-L), 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f/(T-B), 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f - } } }; - g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); - g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); - g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); - } + // Setup desired DX state + ImGui_ImplDX9_SetupRenderState(draw_data); // Render command lists int vtx_offset = 0; @@ -180,9 +187,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != NULL) { - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX9_SetupRenderState(draw_data); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_metal.mm b/examples/imgui_impl_metal.mm index 02eb0f8e..49a7baf0 100644 --- a/examples/imgui_impl_metal.mm +++ b/examples/imgui_impl_metal.mm @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-04-30: Metal: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: Metal: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-07-05: Metal: Added new Metal backend implementation. @@ -58,6 +59,12 @@ - (void)enqueueReusableBuffer:(MetalBuffer *)buffer; - (id)renderPipelineStateForFrameAndDevice:(id)device; - (void)emptyRenderPipelineStateCache; +- (void)setupRenderState:(ImDrawData *)drawData + commandBuffer:(id)commandBuffer + commandEncoder:(id)commandEncoder + renderPipelineState:(id)renderPipelineState + vertexBuffer:(MetalBuffer *)vertexBuffer + vertexBufferOffset:(size_t)vertexBufferOffset; - (void)renderDrawData:(ImDrawData *)drawData commandBuffer:(id)commandBuffer commandEncoder:(id)commandEncoder; @@ -399,16 +406,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects() [self.renderPipelineStateCache removeAllObjects]; } -- (void)renderDrawData:(ImDrawData *)drawData - commandBuffer:(id)commandBuffer - commandEncoder:(id)commandEncoder +- (void)setupRenderState:(ImDrawData *)drawData + commandBuffer:(id)commandBuffer + commandEncoder:(id)commandEncoder + renderPipelineState:(id)renderPipelineState + vertexBuffer:(MetalBuffer *)vertexBuffer + vertexBufferOffset:(size_t)vertexBufferOffset { - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x); - int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y); - if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0) - return; - [commandEncoder setCullMode:MTLCullModeNone]; [commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState]; @@ -419,12 +423,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects() { .originX = 0.0, .originY = 0.0, - .width = double(fb_width), - .height = double(fb_height), + .width = (double)(drawData->DisplaySize.x * drawData->FramebufferScale.x), + .height = (double)(drawData->DisplaySize.y * drawData->FramebufferScale.y), .znear = 0.0, .zfar = 1.0 }; [commandEncoder setViewport:viewport]; + float L = drawData->DisplayPos.x; float R = drawData->DisplayPos.x + drawData->DisplaySize.x; float T = drawData->DisplayPos.y; @@ -438,18 +443,32 @@ void ImGui_ImplMetal_DestroyDeviceObjects() { 0.0f, 0.0f, 1/(F-N), 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f }, }; - [commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1]; + [commandEncoder setRenderPipelineState:renderPipelineState]; + + [commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0]; + [commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0]; +} + +- (void)renderDrawData:(ImDrawData *)drawData + commandBuffer:(id)commandBuffer + commandEncoder:(id)commandEncoder +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x); + int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y); + if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0) + return; + + id renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device]; + size_t vertexBufferLength = drawData->TotalVtxCount * sizeof(ImDrawVert); size_t indexBufferLength = drawData->TotalIdxCount * sizeof(ImDrawIdx); MetalBuffer* vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device]; MetalBuffer* indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device]; - id renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device]; - [commandEncoder setRenderPipelineState:renderPipelineState]; - - [commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0]; + [self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:0]; // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = drawData->DisplayPos; // (0,0) unless using multi-viewports @@ -473,8 +492,12 @@ void ImGui_ImplMetal_DestroyDeviceObjects() const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + [self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:vertexBufferOffset]; + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_opengl2.cpp b/examples/imgui_impl_opengl2.cpp index d5abcc69..bf6209fa 100644 --- a/examples/imgui_impl_opengl2.cpp +++ b/examples/imgui_impl_opengl2.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications. @@ -83,24 +84,9 @@ void ImGui_ImplOpenGL2_NewFrame() ImGui_ImplOpenGL2_CreateDeviceObjects(); } -// OpenGL2 Render function. -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) +static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height) { - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); - int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if (fb_width == 0 || fb_height == 0) - return; - - // We are using the OpenGL fixed pipeline to make the example code simpler to read! // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. - GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); - GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); - GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); @@ -132,6 +118,28 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); +} + +// OpenGL2 Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if (fb_width == 0 || fb_height == 0) + return; + + // Backup GL state + GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); + GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); + GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); + + // Setup desired GL state + ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports @@ -152,8 +160,12 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height); + else + pcmd->UserCallback(cmd_list, pcmd); } else { @@ -178,7 +190,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) } } - // Restore modified state + // Restore modified GL state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/examples/imgui_impl_opengl3.cpp b/examples/imgui_impl_opengl3.cpp index 76471d0b..21fd2573 100644 --- a/examples/imgui_impl_opengl3.cpp +++ b/examples/imgui_impl_opengl3.cpp @@ -14,6 +14,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. // 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. // 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). @@ -162,6 +163,56 @@ void ImGui_ImplOpenGL3_NewFrame() ImGui_ImplOpenGL3_CreateDeviceObjects(); } +static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); +#ifdef GL_POLYGON_MODE + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif + + // Setup viewport, orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. + glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); +#ifdef GL_SAMPLER_BINDING + glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. +#endif + + (void)vertex_array_object; +#ifndef IMGUI_IMPL_OPENGL_ES2 + glBindVertexArray(vertex_array_object); +#endif + + // Bind vertex/index buffers and setup attributes for ImDrawVert + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); + glEnableVertexAttribArray(g_AttribLocationVtxPos); + glEnableVertexAttribArray(g_AttribLocationVtxUV); + glEnableVertexAttribArray(g_AttribLocationVtxColor); + glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); +} + // OpenGL3 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. @@ -207,55 +258,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) clip_origin_lower_left = false; #endif - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -#endif - - // Setup viewport, orthographic projection matrix - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. - glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. -#endif - + // Setup desired GL state // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. -#ifndef IMGUI_IMPL_OPENGL_ES2 GLuint vertex_array_object = 0; +#ifndef IMGUI_IMPL_OPENGL_ES2 glGenVertexArrays(1, &vertex_array_object); - glBindVertexArray(vertex_array_object); #endif - - // Bind vertex/index buffers and setup attributes for ImDrawVert - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); - glEnableVertexAttribArray(g_AttribLocationVtxPos); - glEnableVertexAttribArray(g_AttribLocationVtxUV); - glEnableVertexAttribArray(g_AttribLocationVtxColor); - glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); + ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports @@ -274,10 +284,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != NULL) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index a36a3e38..d260cce3 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -21,8 +21,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2019-XX-XX: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount(). -// 2019-XX-XX: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper. +// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. +// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount(). +// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper. // 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like. // 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int). // 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display. @@ -273,6 +274,49 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory p_buffer_size = new_size; } +static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) +{ + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = { g_DescriptorSet }; + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = { rb->VertexBuffer }; + VkDeviceSize vertex_offset[1] = { 0 }; + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = (float)fb_width; + viewport.height = (float)fb_height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(command_buffer, 0, 1, &viewport); + } + + // Setup scale and translation: + // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. + { + float scale[2]; + scale[0] = 2.0f / draw_data->DisplaySize.x; + scale[1] = 2.0f / draw_data->DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } +} + // Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer) @@ -339,45 +383,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm vkUnmapMemory(v->Device, rb->IndexBufferMemory); } - // Bind pipeline and descriptor sets: - { - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); - VkDescriptorSet desc_set[1] = { g_DescriptorSet }; - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); - } - - // Bind Vertex And Index Buffer: - { - VkBuffer vertex_buffers[1] = { rb->VertexBuffer }; - VkDeviceSize vertex_offset[1] = { 0 }; - vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset); - vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32); - } - - // Setup viewport: - { - VkViewport viewport; - viewport.x = 0; - viewport.y = 0; - viewport.width = (float)fb_width; - viewport.height = (float)fb_height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(command_buffer, 0, 1, &viewport); - } - - // Setup scale and translation: - // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. - { - float scale[2]; - scale[0] = 2.0f / draw_data->DisplaySize.x; - scale[1] = 2.0f / draw_data->DisplaySize.y; - float translate[2]; - translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; - translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; - vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); - vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); - } + // Setup desired Vulkan state + ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports @@ -392,10 +399,14 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != NULL) { - // User callback (registered via ImDrawList::AddCallback) - pcmd->UserCallback(cmd_list, pcmd); + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); + else + pcmd->UserCallback(cmd_list, pcmd); } else { diff --git a/imgui.cpp b/imgui.cpp index dcd83887..af723a4c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -381,6 +381,7 @@ CODE - 2019/04/29 (1.70) - fixed ImDrawList rectangles with thick lines (>1.0f) not being as thick as requested. If you have custom rendering using rectangles with thick lines, they will appear thicker now. + - 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete). - 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete). - 2019/02/26 (1.69) - renamed ImGuiColorEditFlags_RGB/ImGuiColorEditFlags_HSV/ImGuiColorEditFlags_HEX to ImGuiColorEditFlags_DisplayRGB/ImGuiColorEditFlags_DisplayHSV/ImGuiColorEditFlags_DisplayHex. Kept redirection enums (will obsolete). - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with a dummy small value! @@ -7064,11 +7065,6 @@ ImVec2 ImGui::GetContentRegionAvail() return GetContentRegionMaxScreen() - window->DC.CursorPos; } -float ImGui::GetContentRegionAvailWidth() -{ - return GetContentRegionAvail().x; -} - // In window space (not screen space!) ImVec2 ImGui::GetWindowContentRegionMin() { @@ -9435,16 +9431,16 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) return false; } + // Early out + if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) + return false; + // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() // We build a throwaway ID based on current ID stack + relative AABB of items in window. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. - bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0; - if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) - return false; source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); - if (is_hovered) - SetHoveredID(source_id); + bool is_hovered = ItemHoverable(window->DC.LastItemRect, source_id); if (is_hovered && g.IO.MouseClicked[mouse_button]) { SetActiveID(source_id, window); @@ -10051,14 +10047,15 @@ static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler* return (void*)settings; } -static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) +static void SettingsHandlerWindow_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler*, void* entry, const char* line) { + ImGuiContext& g = *ctx; ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; float x, y; int i; ImU32 u1; if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) { settings->Pos = ImVec2(x, y); } - else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) { settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); } + else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) { settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize); } else if (sscanf(line, "ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; } else if (sscanf(line, "ViewportPos=%f,%f", &x, &y) == 2) { settings->ViewportPos = ImVec2(x, y); } else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } diff --git a/imgui.h b/imgui.h index 58f94e4d..b772682d 100644 --- a/imgui.h +++ b/imgui.h @@ -300,7 +300,6 @@ namespace ImGui // - Those functions are bound to be redesigned soon (they are confusing, incomplete and return values in local window coordinates which increases confusion) IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API float GetContentRegionAvailWidth(); // == GetContentRegionAvail().x IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates IMGUI_API float GetWindowContentRegionWidth(); // @@ -1621,6 +1620,8 @@ struct ImGuiWindowClass #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.70 (from May 2019) + static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; } // OBSOLETED in 1.69 (from Mar 2019) static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.66 (from Sep 2018) @@ -1850,11 +1851,18 @@ struct ImColor // Draw callbacks for advanced uses. // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, -// you can poke into the draw list for that! Draw callback may be useful for example to: A) Change your GPU render state, -// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. +// you can poke into the draw list for that! Draw callback may be useful for example to: +// A) Change your GPU render state, +// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); +// Special Draw Callback value to request renderer back-end to reset the graphics/render state. +// The renderer back-end needs to handle this special value, otherwise it will crash trying to call a function at this address. +// This is useful for example if you submitted callbacks which you know have altered the render state and you want it to be restored. +// It is not done by default because they are many perfectly useful way of altering render state for imgui contents (e.g. changing shader/blending settings before an Image call). +#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-1) + // Typically, 1 command = 1 GPU draw call (unless command is a callback) struct ImDrawCmd { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 77191170..c0b19e70 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1810,9 +1810,9 @@ static void ShowDemoWindowLayout() ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.5f); ImGui::DragFloat("float##2", &f); - ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvailWidth() * 0.5f)"); + ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)"); ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)"); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.5f); ImGui::DragFloat("float##3", &f); ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");