mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-11 00:04:24 +00:00
Merge branch 'ocornut:docking' into docking
This commit is contained in:
commit
2f2c59ee53
30 changed files with 617 additions and 395 deletions
2
.github/workflows/static-analysis.yml
vendored
2
.github/workflows/static-analysis.yml
vendored
|
|
@ -42,5 +42,5 @@ jobs:
|
||||||
fi
|
fi
|
||||||
cd examples/example_null
|
cd examples/example_null
|
||||||
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
|
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
|
||||||
pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
|
pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
|
||||||
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
|
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
|
||||||
|
|
|
||||||
|
|
@ -770,7 +770,8 @@ static void ImGui_ImplDX10_RenderViewport(ImGuiViewport* viewport, void*)
|
||||||
static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport, void*)
|
static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||||
{
|
{
|
||||||
ImGui_ImplDX10_ViewportData* vd = (ImGui_ImplDX10_ViewportData*)viewport->RendererUserData;
|
ImGui_ImplDX10_ViewportData* vd = (ImGui_ImplDX10_ViewportData*)viewport->RendererUserData;
|
||||||
vd->SwapChain->Present(0, 0); // Present without vsync
|
if (vd->SwapChain)
|
||||||
|
vd->SwapChain->Present(0, 0); // Present without vsync
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplDX10_InitMultiViewportSupport()
|
void ImGui_ImplDX10_InitMultiViewportSupport()
|
||||||
|
|
|
||||||
|
|
@ -800,7 +800,8 @@ static void ImGui_ImplDX11_RenderWindow(ImGuiViewport* viewport, void*)
|
||||||
static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport, void*)
|
static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||||
{
|
{
|
||||||
ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData;
|
ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData;
|
||||||
vd->SwapChain->Present(0, 0); // Present without vsync
|
if (vd->SwapChain)
|
||||||
|
vd->SwapChain->Present(0, 0); // Present without vsync
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplDX11_InitMultiViewportSupport()
|
static void ImGui_ImplDX11_InitMultiViewportSupport()
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2025-10-23: [Docking] DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#8961, #9025)
|
||||||
|
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
|
||||||
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
|
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
|
||||||
// 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965)
|
// 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965)
|
||||||
// 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963)
|
// 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963)
|
||||||
|
|
@ -111,9 +113,9 @@ struct ImGui_ImplDX12_Data
|
||||||
|
|
||||||
ID3D12CommandAllocator* pTexCmdAllocator;
|
ID3D12CommandAllocator* pTexCmdAllocator;
|
||||||
ID3D12GraphicsCommandList* pTexCmdList;
|
ID3D12GraphicsCommandList* pTexCmdList;
|
||||||
|
ID3D12Resource* pTexUploadBuffer;
|
||||||
ImGui_ImplDX12_RenderBuffers* pFrameResources;
|
UINT pTexUploadBufferSize;
|
||||||
UINT frameIndex;
|
void* pTexUploadBufferMapped;
|
||||||
|
|
||||||
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); }
|
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
@ -293,8 +295,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||||
// FIXME: We are assuming that this only gets called once per frame!
|
// FIXME: We are assuming that this only gets called once per frame!
|
||||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||||
ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)draw_data->OwnerViewport->RendererUserData;
|
ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)draw_data->OwnerViewport->RendererUserData;
|
||||||
vd->FrameIndex++;
|
|
||||||
ImGui_ImplDX12_RenderBuffers* fr = &vd->FrameRenderBuffers[vd->FrameIndex % bd->numFramesInFlight];
|
ImGui_ImplDX12_RenderBuffers* fr = &vd->FrameRenderBuffers[vd->FrameIndex % bd->numFramesInFlight];
|
||||||
|
vd->FrameIndex++;
|
||||||
|
|
||||||
// Create and grow vertex/index buffers if needed
|
// Create and grow vertex/index buffers if needed
|
||||||
if (fr->VertexBuffer == nullptr || fr->VertexBufferSize < draw_data->TotalVtxCount)
|
if (fr->VertexBuffer == nullptr || fr->VertexBufferSize < draw_data->TotalVtxCount)
|
||||||
|
|
@ -516,44 +518,53 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||||
UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||||
UINT upload_size = upload_pitch_dst * upload_h;
|
UINT upload_size = upload_pitch_dst * upload_h;
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC desc;
|
if (bd->pTexUploadBuffer == nullptr || upload_size > bd->pTexUploadBufferSize)
|
||||||
ZeroMemory(&desc, sizeof(desc));
|
{
|
||||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
if (bd->pTexUploadBufferMapped)
|
||||||
desc.Alignment = 0;
|
{
|
||||||
desc.Width = upload_size;
|
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
|
||||||
desc.Height = 1;
|
bd->pTexUploadBuffer->Unmap(0, &range);
|
||||||
desc.DepthOrArraySize = 1;
|
bd->pTexUploadBufferMapped = nullptr;
|
||||||
desc.MipLevels = 1;
|
}
|
||||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
SafeRelease(bd->pTexUploadBuffer);
|
||||||
desc.SampleDesc.Count = 1;
|
|
||||||
desc.SampleDesc.Quality = 0;
|
|
||||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES props;
|
D3D12_RESOURCE_DESC desc;
|
||||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
desc.Alignment = 0;
|
||||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
desc.Width = upload_size;
|
||||||
|
desc.Height = 1;
|
||||||
|
desc.DepthOrArraySize = 1;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
// FIXME-OPT: Could upload buffer be kept around, reused, and grown only when needed? Would that be worth it?
|
D3D12_HEAP_PROPERTIES props;
|
||||||
ID3D12Resource* uploadBuffer = nullptr;
|
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||||
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
|
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
IM_ASSERT(SUCCEEDED(hr));
|
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
|
|
||||||
|
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bd->pTexUploadBuffer));
|
||||||
|
IM_ASSERT(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
D3D12_RANGE range = {0, upload_size};
|
||||||
|
hr = bd->pTexUploadBuffer->Map(0, &range, &bd->pTexUploadBufferMapped);
|
||||||
|
IM_ASSERT(SUCCEEDED(hr));
|
||||||
|
bd->pTexUploadBufferSize = upload_size;
|
||||||
|
}
|
||||||
|
|
||||||
bd->pTexCmdAllocator->Reset();
|
bd->pTexCmdAllocator->Reset();
|
||||||
bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
|
bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
|
||||||
ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
|
ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
|
||||||
|
|
||||||
// Copy to upload buffer
|
// Copy to upload buffer
|
||||||
void* mapped = nullptr;
|
|
||||||
D3D12_RANGE range = { 0, upload_size };
|
|
||||||
hr = uploadBuffer->Map(0, &range, &mapped);
|
|
||||||
IM_ASSERT(SUCCEEDED(hr));
|
|
||||||
for (int y = 0; y < upload_h; y++)
|
for (int y = 0; y < upload_h; y++)
|
||||||
memcpy((void*)((uintptr_t)mapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
|
memcpy((void*)((uintptr_t)bd->pTexUploadBufferMapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
|
||||||
uploadBuffer->Unmap(0, &range);
|
|
||||||
|
|
||||||
if (need_barrier_before_copy)
|
if (need_barrier_before_copy)
|
||||||
{
|
{
|
||||||
|
|
@ -570,7 +581,7 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||||
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
||||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||||
{
|
{
|
||||||
srcLocation.pResource = uploadBuffer;
|
srcLocation.pResource = bd->pTexUploadBuffer;
|
||||||
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||||
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
srcLocation.PlacedFootprint.Footprint.Width = upload_w;
|
srcLocation.PlacedFootprint.Footprint.Width = upload_w;
|
||||||
|
|
@ -594,9 +605,8 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||||
cmdList->ResourceBarrier(1, &barrier);
|
cmdList->ResourceBarrier(1, &barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = cmdList->Close();
|
HRESULT hr = cmdList->Close();
|
||||||
IM_ASSERT(SUCCEEDED(hr));
|
IM_ASSERT(SUCCEEDED(hr));
|
||||||
|
|
||||||
ID3D12CommandQueue* cmdQueue = bd->pCommandQueue;
|
ID3D12CommandQueue* cmdQueue = bd->pCommandQueue;
|
||||||
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
|
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
|
||||||
hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue);
|
hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue);
|
||||||
|
|
@ -609,7 +619,6 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
|
||||||
bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent);
|
bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent);
|
||||||
::WaitForSingleObject(bd->FenceEvent, INFINITE);
|
::WaitForSingleObject(bd->FenceEvent, INFINITE);
|
||||||
|
|
||||||
uploadBuffer->Release();
|
|
||||||
tex->SetStatus(ImTextureStatus_OK);
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -889,6 +898,13 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
|
||||||
bd->commandQueueOwned = false;
|
bd->commandQueueOwned = false;
|
||||||
SafeRelease(bd->pRootSignature);
|
SafeRelease(bd->pRootSignature);
|
||||||
SafeRelease(bd->pPipelineState);
|
SafeRelease(bd->pPipelineState);
|
||||||
|
if (bd->pTexUploadBufferMapped)
|
||||||
|
{
|
||||||
|
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
|
||||||
|
bd->pTexUploadBuffer->Unmap(0, &range);
|
||||||
|
bd->pTexUploadBufferMapped = nullptr;
|
||||||
|
}
|
||||||
|
SafeRelease(bd->pTexUploadBuffer);
|
||||||
SafeRelease(bd->pTexCmdList);
|
SafeRelease(bd->pTexCmdList);
|
||||||
SafeRelease(bd->pTexCmdAllocator);
|
SafeRelease(bd->pTexCmdAllocator);
|
||||||
SafeRelease(bd->Fence);
|
SafeRelease(bd->Fence);
|
||||||
|
|
@ -1265,7 +1281,6 @@ static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||||
ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)viewport->RendererUserData;
|
ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)viewport->RendererUserData;
|
||||||
|
|
||||||
vd->SwapChain->Present(0, bd->tearingSupport ? DXGI_PRESENT_ALLOW_TEARING : 0);
|
vd->SwapChain->Present(0, bd->tearingSupport ? DXGI_PRESENT_ALLOW_TEARING : 0);
|
||||||
vd->FrameIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplDX12_InitMultiViewportSupport()
|
void ImGui_ImplDX12_InitMultiViewportSupport()
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,6 @@
|
||||||
#define GLFW_EXPOSE_NATIVE_X11
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
|
|
||||||
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
|
||||||
#endif
|
|
||||||
#include <GLFW/glfw3native.h>
|
#include <GLFW/glfw3native.h>
|
||||||
#undef Status // X11 headers are leaking this.
|
#undef Status // X11 headers are leaking this.
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core).
|
||||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||||
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
|
// 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414)
|
||||||
|
|
@ -570,7 +571,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
||||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
|
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText;
|
||||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
|
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText;
|
||||||
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
|
platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData;
|
||||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; };
|
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); };
|
||||||
|
|
||||||
// Update monitor a first time during init
|
// Update monitor a first time during init
|
||||||
ImGui_ImplSDL3_UpdateMonitors();
|
ImGui_ImplSDL3_UpdateMonitors();
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008)
|
||||||
// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.
|
// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.
|
||||||
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
|
// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.
|
||||||
// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
|
// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,14 @@
|
||||||
// If you have no idea what this is, leave it alone!
|
// If you have no idea what this is, leave it alone!
|
||||||
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||||
|
|
||||||
// Convenience support for Volk
|
// [Configuration] Convenience support for Volk
|
||||||
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
|
// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
|
||||||
|
// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,
|
||||||
|
// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')
|
||||||
//#define IMGUI_IMPL_VULKAN_USE_VOLK
|
//#define IMGUI_IMPL_VULKAN_USE_VOLK
|
||||||
|
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <Volk/volk.h>
|
||||||
|
//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME <volk.h> // Default
|
||||||
|
// Reminder: make those changes in your imconfig.h file, not here!
|
||||||
|
|
||||||
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
|
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
|
||||||
#define VK_NO_PROTOTYPES
|
#define VK_NO_PROTOTYPES
|
||||||
|
|
@ -55,7 +60,11 @@
|
||||||
|
|
||||||
// Vulkan includes
|
// Vulkan includes
|
||||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||||
|
#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||||
|
#include IMGUI_IMPL_VULKAN_VOLK_FILENAME
|
||||||
|
#else
|
||||||
#include <volk.h>
|
#include <volk.h>
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// dear imgui: Renderer for WebGPU
|
// dear imgui: Renderer for WebGPU
|
||||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
|
||||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
// Missing features or Issues:
|
// Missing features or Issues:
|
||||||
// [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop.
|
// [ ] Renderer: Multi-viewport support (multiple windows), useful for desktop.
|
||||||
|
|
||||||
|
// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
// Learn about Dear ImGui:
|
// Learn about Dear ImGui:
|
||||||
|
|
@ -20,6 +22,7 @@
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
|
// 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465)
|
||||||
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
|
// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes.
|
||||||
|
|
@ -48,20 +51,20 @@
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
|
||||||
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
|
|
||||||
#ifndef __EMSCRIPTEN__
|
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
#error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE
|
#ifndef IMGUI_DISABLE
|
||||||
#include "imgui_impl_wgpu.h"
|
#include "imgui_impl_wgpu.h"
|
||||||
|
|
||||||
|
// One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This condition is true when it's built with EMSCRIPTEN using -sUSE_WEBGPU=1 flag (deprecated from 4.0.10)
|
||||||
|
// This condition is false for all other 3 cases: WGPU-Native, DAWN-Native or DAWN-EMSCRIPTEN (using --use-port=emdawnwebgpu flag)
|
||||||
|
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
|
|
||||||
|
|
@ -261,7 +264,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
|
||||||
{
|
{
|
||||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||||
|
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
WGPUShaderSourceWGSL wgsl_desc = {};
|
WGPUShaderSourceWGSL wgsl_desc = {};
|
||||||
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
|
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
|
||||||
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
|
wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
|
||||||
|
|
@ -277,7 +280,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
|
||||||
WGPUProgrammableStageDescriptor stage_desc = {};
|
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||||
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
||||||
|
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||||
#else
|
#else
|
||||||
stage_desc.entryPoint = "main";
|
stage_desc.entryPoint = "main";
|
||||||
|
|
@ -400,9 +403,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||||
WGPUBufferDescriptor vb_desc =
|
WGPUBufferDescriptor vb_desc =
|
||||||
{
|
{
|
||||||
nullptr,
|
nullptr,
|
||||||
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
|
{ "Dear ImGui Vertex buffer", WGPU_STRLEN, },
|
||||||
|
#else
|
||||||
"Dear ImGui Vertex buffer",
|
"Dear ImGui Vertex buffer",
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
WGPU_STRLEN,
|
|
||||||
#endif
|
#endif
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
|
||||||
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
|
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
|
||||||
|
|
@ -427,9 +431,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||||
WGPUBufferDescriptor ib_desc =
|
WGPUBufferDescriptor ib_desc =
|
||||||
{
|
{
|
||||||
nullptr,
|
nullptr,
|
||||||
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
|
{ "Dear ImGui Index buffer", WGPU_STRLEN, },
|
||||||
|
#else
|
||||||
"Dear ImGui Index buffer",
|
"Dear ImGui Index buffer",
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
WGPU_STRLEN,
|
|
||||||
#endif
|
#endif
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
|
||||||
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
|
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
|
||||||
|
|
@ -562,7 +567,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||||
|
|
||||||
// Create texture
|
// Create texture
|
||||||
WGPUTextureDescriptor tex_desc = {};
|
WGPUTextureDescriptor tex_desc = {};
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN };
|
tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN };
|
||||||
#else
|
#else
|
||||||
tex_desc.label = "Dear ImGui Texture";
|
tex_desc.label = "Dear ImGui Texture";
|
||||||
|
|
@ -607,7 +612,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||||
|
|
||||||
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
|
// Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
|
||||||
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
|
// This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
WGPUTexelCopyTextureInfo dst_view = {};
|
WGPUTexelCopyTextureInfo dst_view = {};
|
||||||
#else
|
#else
|
||||||
WGPUImageCopyTexture dst_view = {};
|
WGPUImageCopyTexture dst_view = {};
|
||||||
|
|
@ -616,7 +621,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
||||||
dst_view.mipLevel = 0;
|
dst_view.mipLevel = 0;
|
||||||
dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 };
|
dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 };
|
||||||
dst_view.aspect = WGPUTextureAspect_All;
|
dst_view.aspect = WGPUTextureAspect_All;
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
WGPUTexelCopyBufferLayout layout = {};
|
WGPUTexelCopyBufferLayout layout = {};
|
||||||
#else
|
#else
|
||||||
WGPUTextureDataLayout layout = {};
|
WGPUTextureDataLayout layout = {};
|
||||||
|
|
@ -638,9 +643,10 @@ static void ImGui_ImplWGPU_CreateUniformBuffer()
|
||||||
WGPUBufferDescriptor ub_desc =
|
WGPUBufferDescriptor ub_desc =
|
||||||
{
|
{
|
||||||
nullptr,
|
nullptr,
|
||||||
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
|
{ "Dear ImGui Uniform buffer", WGPU_STRLEN, },
|
||||||
|
#else
|
||||||
"Dear ImGui Uniform buffer",
|
"Dear ImGui Uniform buffer",
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
WGPU_STRLEN,
|
|
||||||
#endif
|
#endif
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
|
||||||
MEMALIGN(sizeof(Uniforms), 16),
|
MEMALIGN(sizeof(Uniforms), 16),
|
||||||
|
|
@ -753,7 +759,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||||
// Create depth-stencil State
|
// Create depth-stencil State
|
||||||
WGPUDepthStencilState depth_stencil_state = {};
|
WGPUDepthStencilState depth_stencil_state = {};
|
||||||
depth_stencil_state.format = bd->depthStencilFormat;
|
depth_stencil_state.format = bd->depthStencilFormat;
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN)
|
||||||
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
||||||
#else
|
#else
|
||||||
depth_stencil_state.depthWriteEnabled = false;
|
depth_stencil_state.depthWriteEnabled = false;
|
||||||
|
|
@ -835,14 +841,18 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
|
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
|
||||||
io.BackendRendererUserData = (void*)bd;
|
io.BackendRendererUserData = (void*)bd;
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
io.BackendRendererName = "imgui_impl_webgpu_emscripten";
|
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Emscripten)"; // compiled & linked using EMSCRIPTEN with "--use-port=emdawnwebgpu" flag
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
|
||||||
io.BackendRendererName = "imgui_impl_webgpu_dawn";
|
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
io.BackendRendererName = "imgui_impl_webgpu_wgpu";
|
|
||||||
#else
|
#else
|
||||||
io.BackendRendererName = "imgui_impl_webgpu";
|
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
|
||||||
|
#endif
|
||||||
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Emscripten)"; // linked using EMSCRIPTEN with "-sUSE_WEBGPU=1" flag, deprecated from EMSCRIPTEN 4.0.10
|
||||||
|
#else
|
||||||
|
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
// dear imgui: Renderer for WebGPU
|
// dear imgui: Renderer for WebGPU
|
||||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3)
|
||||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||||
|
|
||||||
// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
|
// When targeting native platforms:
|
||||||
// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
|
// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU *must* be provided.
|
||||||
|
// When targeting Emscripten:
|
||||||
|
// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN is Emscripten version is 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
|
||||||
|
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
|
||||||
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
|
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
|
||||||
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
|
// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface.
|
||||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
|
|
@ -29,12 +32,22 @@
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
#ifndef IMGUI_DISABLE
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
|
// Setup Emscripten default if not specified.
|
||||||
|
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
#include <emscripten/version.h>
|
||||||
|
#if (__EMSCRIPTEN_major__ >= 4) && (__EMSCRIPTEN_minor__ >= 0) && (__EMSCRIPTEN_tiny__ >= 10)
|
||||||
|
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||||
|
#else
|
||||||
|
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
|
|
||||||
// Initialization data, for ImGui_ImplWGPU_Init()
|
// Initialization data, for ImGui_ImplWGPU_Init()
|
||||||
struct ImGui_ImplWGPU_InitInfo
|
struct ImGui_ImplWGPU_InitInfo
|
||||||
{
|
{
|
||||||
WGPUDevice Device;
|
WGPUDevice Device = nullptr;
|
||||||
int NumFramesInFlight = 3;
|
int NumFramesInFlight = 3;
|
||||||
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
|
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
|
||||||
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
|
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||||
|
|
|
||||||
|
|
@ -36,125 +36,214 @@ HOW TO UPDATE?
|
||||||
- Please report any issue!
|
- Please report any issue!
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
VERSION 1.92.4 WIP (In Progress)
|
VERSION 1.92.5 WIP (In Progress)
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
Breaking Changes:
|
Breaking Changes:
|
||||||
|
|
||||||
|
Other Changes:
|
||||||
|
|
||||||
|
- Tables: fixed a bug where nesting BeginTable()->Begin()->BeginTable() would
|
||||||
|
result in temporarily incorrect state, which would lead to bugs to side effects
|
||||||
|
in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005)
|
||||||
|
EndTable() was mistakenly restoring a wrong current table.
|
||||||
|
- InputText: when buffer is not resizable, trying to paste contents that
|
||||||
|
cannot fit will now truncate text instead of ignoring the paste. (#9029)
|
||||||
|
- InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter
|
||||||
|
keys in order to allow e.g. external Shortcut override behavior. (#9004)
|
||||||
|
- InputText: when using a callback to reduce/manipulate the value of BufTextLen,
|
||||||
|
we do not require anymore that CursorPos be clamped by user code. (#9029)
|
||||||
|
- InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and
|
||||||
|
resizing the parent window while keeping the multi-line field active (which is
|
||||||
|
most typically achieved when resizing programmatically or via a docking layout
|
||||||
|
reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut]
|
||||||
|
- MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default
|
||||||
|
right-click processing, which selects item on mouse down and is designed for
|
||||||
|
context-menus. (#8200, #9015)
|
||||||
|
- Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() when
|
||||||
|
triggered by some widgets e.g. Checkbox(), Selectable() and many others, which
|
||||||
|
cleared ActiveId at the same time as editing. (#9028)
|
||||||
|
Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited).
|
||||||
|
- Backends:
|
||||||
|
- GLFW: fixed building on Linux platforms where Wayland headers
|
||||||
|
are not available. (#9024, #8969, #8921, #8920) [@jagot]
|
||||||
|
- SDL3: fixed Platform_OpenInShellFn() return value (the return value
|
||||||
|
was unused in core but might be used by a direct caller). (#9027) [@achabense]
|
||||||
|
- Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to
|
||||||
|
Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk]
|
||||||
|
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
|
||||||
|
'--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb]
|
||||||
|
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||||
|
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
|
||||||
|
(note: examples application were not updated yet)
|
||||||
|
- Examples:
|
||||||
|
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
|
||||||
|
during surface resize. (#8381)
|
||||||
|
|
||||||
|
Docking+Viewports Branch:
|
||||||
|
|
||||||
|
- Examples:
|
||||||
|
- SDL2+DX11, SDL3+DX11, Win32+DX10, Win32+DX11: fixed one resource leak
|
||||||
|
from the use of MakeWindowAssociation() in 1.92.4. (#9010, #4350) [@o-3-o]
|
||||||
|
- Backends:
|
||||||
|
- DirectX12: Fixed an issue in synchronization logic improving rendering
|
||||||
|
throughput for secondary viewports. (#9025, #8961)
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
VERSION 1.92.4 (Released 2025-10-14)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.4
|
||||||
|
|
||||||
|
Breaking Changes:
|
||||||
|
|
||||||
- Viewports: for consistency with other config flags, renamed
|
- Viewports: for consistency with other config flags, renamed
|
||||||
io.ConfigViewportPlatformFocusSetsImGuiFocus
|
io.ConfigViewportPlatformFocusSetsImGuiFocus
|
||||||
to io.ConfigViewportsPlatformFocusSetsImGuiFocus. (#6299, #6462)
|
to io.ConfigViewportsPlatformFocusSetsImGuiFocus. (#6299, #6462)
|
||||||
It was really a typo in the first place, and introduced in 1.92.2.
|
It was really a typo in the first place, and introduced in 1.92.2.
|
||||||
- Backends: Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
|
- Backends:
|
||||||
init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass
|
- TreeNode, Selectable, Clipper: commented out legacy names obsoleted in
|
||||||
init_info.Subpass --> init_info.PipelineInfoMain.Subpass
|
1.89.7 (July 2023) and 1.89.9 (Sept 2023):
|
||||||
init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples
|
ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap
|
||||||
init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo
|
ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap
|
||||||
It makes things more consistent and was desirable to introduce new settings for
|
ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex()
|
||||||
secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz]
|
- Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
|
||||||
- Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
|
init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass
|
||||||
(introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()`
|
init_info.Subpass --> init_info.PipelineInfoMain.Subpass
|
||||||
so it should not affect many users). (#8110, #8111)
|
init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples
|
||||||
- Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
|
init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo
|
||||||
`VkImageUsageFlags image_usage` argument to specific extra flags for calls to
|
It makes things more consistent and was desirable to introduce new settings for
|
||||||
vkCreateSwapchainKHR() done for secondary viewports. We automatically add
|
secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz]
|
||||||
`VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT`. In theory the function is an internal
|
- Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
|
||||||
helper but since it's used by our examples some may have used it. (#8946, #8111, #8686)
|
(introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()`
|
||||||
|
so it should not affect many users). (#8110, #8111)
|
||||||
|
- Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
|
||||||
|
`VkImageUsageFlags image_usage` argument.
|
||||||
|
It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults
|
||||||
|
to that when the value is 0. In theory the function is an internal helper but
|
||||||
|
since it's used by our examples some may have used it. (#8946, #8111, #8686)
|
||||||
|
|
||||||
Other Changes:
|
Other Changes:
|
||||||
|
|
||||||
- Windows: added lower-right resize grip on child windows using both
|
- Windows: added lower-right resize grip on child windows using both
|
||||||
ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani]
|
ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani]
|
||||||
The grip is not visible before hovering to reduce clutter.
|
The grip is not visible before hovering to reduce clutter.
|
||||||
- InputText: fixed single-line InputText() not applying fine character clipping
|
- Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when
|
||||||
properly (regression in 1.92.3). (#8967) [@Cyphall]
|
using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983)
|
||||||
- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers()
|
- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers()
|
||||||
helpers to null all handlers. (#8945, #2769)
|
helpers to null all handlers. (#8945, #2769)
|
||||||
|
- Inputs:
|
||||||
|
- Shortcuts: added support for combining ImGuiInputFlags_RouteFocused
|
||||||
|
(which is the default route) with ImGuiInputFlags_RouteOverActive, allowing
|
||||||
|
to steal shortcuts from active item without using global routing. (#9004)
|
||||||
|
- InputText:
|
||||||
|
- Fixed single-line InputText() not applying fine character clipping
|
||||||
|
properly (regression in 1.92.3). (#8967) [@Cyphall]
|
||||||
|
- Fixed an infinite loop error happening if a custom input text
|
||||||
|
callback modifies/clear BufTextLen before calling InsertChars().
|
||||||
|
(regression from 1.92.3). Note that this never really worked correctly, but
|
||||||
|
previously it would only temporary wreck cursor position, and since 1.92.3 it
|
||||||
|
would go in an infinite loop. (#8994, #3237)
|
||||||
|
- Textures:
|
||||||
|
- Fixed a crash if texture status is set to ImTextureStatus_WantDestroy by a backend
|
||||||
|
after it had already been destroyed. This would typically happen when calling
|
||||||
|
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
|
||||||
|
- Allowed backend to destroy texture while inside the NewFrame/EndFrame
|
||||||
|
scope. Basically if a backend decide to destroy a texture that we didn't request
|
||||||
|
to destroy (for e.g. freeing resources) the texture is immediately set to
|
||||||
|
a ImTextureStatus_WantCreate status again. (#8811)
|
||||||
|
- Fixed an issue preventing multi-contexts sharing a ImFontAtlas from
|
||||||
|
being possible to destroy in any order.
|
||||||
|
- Fixed not updating ImTextureData's RefCount when destroying a context
|
||||||
|
using a shared ImFontAtlas, leading standard backends to not properly
|
||||||
|
free texture resources. (#8975) [@icrashstuff]
|
||||||
|
- Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section.
|
||||||
|
- Misc: Relaxed internal assert in MarkItemEdited() to allow for more use cases. (#8997)
|
||||||
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
|
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
|
||||||
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
|
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
|
||||||
See misc/debuggers/ for details. (#8950) [@mentlerd]
|
See misc/debuggers/ for details. (#8950) [@mentlerd]
|
||||||
- Textures: fixed a crash if texture status is set to _WantDestroy by a backend after
|
- CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
|
||||||
it had already been destroyed. This would typically happen when calling backend's
|
|
||||||
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
|
|
||||||
- Textures: allowed backend to destroy texture while inside the NewFrame/EndFrame
|
|
||||||
scope. Basically if a backend decide to destroy a texture that we didn't request
|
|
||||||
to destroy (for e.g. freeing resources) the texture is immediately set to
|
|
||||||
a _WantCreate status again. (#8811)
|
|
||||||
- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from
|
|
||||||
being possible to destroy in any order.
|
|
||||||
- Textures: fixed not updating ImTextureData's RefCount when destroying a context
|
|
||||||
using a shared ImFontAtlas, leading standard backends to not properly free
|
|
||||||
texture resources. (#8975) [@icrashstuff]
|
|
||||||
- CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
|
|
||||||
- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and
|
|
||||||
ClearRendererHandlers() on shutdown, so as not to leave function pointers
|
|
||||||
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
|
|
||||||
- Docs: updated FAQ with new "What is the difference between Dear ImGui and
|
- Docs: updated FAQ with new "What is the difference between Dear ImGui and
|
||||||
traditional UI toolkits?" entry. (#8862)
|
traditional UI toolkits?" entry. (#8862)
|
||||||
- Backends: DirectX12: reuse a command list and allocator for texture uploads instead
|
- Backends:
|
||||||
of recreating them each time. (#8963, #8465) [@RT2Code]
|
- All backends call ImGuiPlatformIO::ClearPlatformHandlers() and
|
||||||
- Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
ClearRendererHandlers() on shutdown, so as not to leave function pointers
|
||||||
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
|
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
|
||||||
- Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
|
- DirectX12: reuse a command list and allocator for texture uploads instead
|
||||||
- Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support
|
of recreating them each time. (#8963, #8465) [@RT2Code]
|
||||||
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
|
- DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||||
- Backends: GLFW: fixed build on platform that are neither Windows, macOS or
|
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
|
||||||
known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion]
|
- DirectX12: Reuse texture upload buffer and grow it only when
|
||||||
- Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
|
necessary. (#9002) [@RT2Code]
|
||||||
window is hovered, as the event data is reliable and enough in this case.
|
- DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
|
||||||
- Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786)
|
- OpenGL3: fixed GL loader to work on Haiku OS which does not support
|
||||||
- Essentially a working for SDL3 bug which will be fixed in SDL 3.3.0.
|
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
|
||||||
- Better perf on X11 as querying global position requires a round trip to X11 server.
|
- GLFW: fixed build on platform that are neither Windows, macOS or
|
||||||
- Backends: Win32: minor optimization not submitting gamepad io again if
|
known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion]
|
||||||
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
|
- SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
|
||||||
- Backends: Vulkan: added a way to specify custom shaders by filling init fields
|
window is hovered, as the event data is reliable and enough in this case.
|
||||||
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
|
- Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786)
|
||||||
- Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
|
- Essentially a workaround for SDL3 bug which will be fixed in SDL 3.3.0.
|
||||||
ensure that a texture in _WantDestroy state always turn to _Destroyed even
|
- Better perf on X11 as querying global position requires a round trip to X11 server.
|
||||||
if your underlying graphics data was already destroyed. (#8977)
|
- Win32: minor optimization not submitting gamepad io again if
|
||||||
- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is
|
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
|
||||||
not available. (#5924, #5562)
|
- Vulkan: added a way to specify custom shaders by filling init fields
|
||||||
- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
|
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
|
||||||
- Examples: Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
- DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
|
||||||
- Examples: made examples's main.cpp consistent with returning 1 on error.
|
ensure that a texture in ImTextureStatus_WantDestroy state always turn to
|
||||||
|
ImTextureStatus_Destroyed even if your underlying graphics data was already
|
||||||
|
destroyed. (#8977)
|
||||||
|
- Examples:
|
||||||
|
- SDL2+DirectX11: Try WARP software driver if hardware driver is
|
||||||
|
not available. (#5924, #5562)
|
||||||
|
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
|
||||||
|
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||||
|
- Made examples's main.cpp consistent with returning 1 on error.
|
||||||
|
|
||||||
Docking+Viewports Branch:
|
Docking+Viewports Branch:
|
||||||
|
|
||||||
- Nav: fixed a crash that could occur when opening a popup following the processing
|
- Nav, Docking, Selection: Fixed tab change from reinitializing navigation state,
|
||||||
|
which would erroneously clear selection when using ImGuiSelectableFlags_SelectOnNav
|
||||||
|
or clear multi-selection when not using ImGuiMultiSelectFlags_NoAutoSelect. (#8997)
|
||||||
|
- Nav: Fixed a crash that could occur when opening a popup following the processing
|
||||||
of a global shortcut while no windows were focused (the fix done in 1.92.3 was
|
of a global shortcut while no windows were focused (the fix done in 1.92.3 was
|
||||||
incomplete for docking branch).
|
incomplete for docking branch).
|
||||||
- Viewports: added ImGuiBackendFlags_HasParentViewport backend flag for
|
- Viewports:
|
||||||
backend to specify if it can honor the viewport->ParentViewportId value by
|
- Added ImGuiBackendFlags_HasParentViewport backend flag for
|
||||||
applying the corresponding parent/child relation at the Platform level. (#8948)
|
backend to specify if it can honor the `viewport->ParentViewport`/`ParentViewportId`
|
||||||
- SDL3, Win32 backends: supported.
|
value by applying the corresponding parent/child relation at the Platform level. (#8948)
|
||||||
- SDL2, GLFW, OSX backends: unsupported.
|
- SDL3, Win32 backends: supported.
|
||||||
- Viewports: fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectivey
|
- SDL2, GLFW, OSX backends: unsupported.
|
||||||
be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann]
|
- Fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectively
|
||||||
- Viewports: changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948)
|
be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann]
|
||||||
- Viewports: fixed an issue inferring Z-order when attempting to merge a viewport
|
- Changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948)
|
||||||
back in the the main/hosting viewport. (#8948)
|
- Fixed an issue inferring Z-order when attempting to merge a viewport
|
||||||
Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID.
|
back in the the main/hosting viewport. (#8948)
|
||||||
setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation
|
Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID.
|
||||||
with what the backend does.
|
Setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation
|
||||||
- Viewports: storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID.
|
with what the backend does.
|
||||||
- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at
|
- Storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID.
|
||||||
it assumed to be unnecessary as backensd should have done it and we check that
|
- ImGui::DestroyContext() does not call DestroyPlatformWindows() anymore at it
|
||||||
backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945)
|
is assumed to be unnecessary as backends should have done it and we check that
|
||||||
- Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary
|
backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945)
|
||||||
viewports managed by the backend. (#4350) [@PathogenDavid]
|
- Backends:
|
||||||
- Backends: Vulkan: Added a way to configure secondary viewport pipelinen creation
|
- DirectX10, DirectX11, DirectX12: Disabled DXGI's Alt+Enter default behavior on
|
||||||
by setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686)
|
secondary viewports managed by the backend. (#4350) [@PathogenDavid]
|
||||||
- Backends: Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags
|
- DirectX10, DirectX11: avoid ImGui_ImplXXXX_SwapBuffers() handlers for secondary
|
||||||
to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut]
|
viewports crashing if SwapChain could not be created.
|
||||||
Usage example:
|
- Vulkan: Added a way to configure secondary viewport pipeline creation by
|
||||||
`init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;`
|
setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686)
|
||||||
- Backends: Vulkan: pipeline created for secondary viewport automatically match
|
- Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags
|
||||||
surface format. (#8686) [@sylmroz]
|
to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut]
|
||||||
- Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper.
|
Usage example: `init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;`
|
||||||
(#8946, #8940) [@olivier-gerard]
|
- Vulkan: pipeline created for secondary viewport automatically match
|
||||||
|
surface format. (#8686) [@sylmroz]
|
||||||
|
- Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard]
|
||||||
|
- Docs: improve docking API comments and demo. (#9000)
|
||||||
- Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples.
|
- Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples.
|
||||||
Applications are free to leave this enabled, but it does not work properly with
|
Applications are free to leave this enabled, but it does not work properly with
|
||||||
multiple viewports. (#4350) [@PathogenDavid]
|
multiple viewports. (#4350, #8979) [@PathogenDavid]
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ if(EMSCRIPTEN)
|
||||||
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
||||||
endif()
|
endif()
|
||||||
set(LIBRARIES glfw)
|
set(LIBRARIES glfw)
|
||||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1 -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
else()
|
else()
|
||||||
# Dawn wgpu desktop
|
# Dawn wgpu desktop
|
||||||
set(DAWN_FETCH_DEPENDENCIES ON)
|
set(DAWN_FETCH_DEPENDENCIES ON)
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,16 @@ EMS =
|
||||||
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
||||||
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
|
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
|
||||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
|
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
|
||||||
LDFLAGS += -s USE_WEBGPU=1
|
|
||||||
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
||||||
|
|
||||||
|
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
||||||
|
EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
LDFLAGS += -s USE_WEBGPU=1
|
||||||
|
|
||||||
|
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10) (UNSUPPORTED YET)
|
||||||
|
#EMS += --use-port=emdawnwebgpu
|
||||||
|
#LDFLAGS += --use-port=emdawnwebgpu
|
||||||
|
|
||||||
# Build as single file (binary text encoded in .html file)
|
# Build as single file (binary text encoded in .html file)
|
||||||
#LDFLAGS += -sSINGLE_FILE
|
#LDFLAGS += -sSINGLE_FILE
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Dear ImGui: standalone example application for using GLFW + WebGPU
|
// Dear ImGui: standalone example application for GLFW + WebGPU
|
||||||
// - Emscripten is supported for publishing on web. See https://emscripten.org.
|
// - Emscripten is supported for publishing on web. See https://emscripten.org.
|
||||||
// - Dawn is used as a WebGPU implementation on desktop.
|
// - Dawn is used as a WebGPU implementation on desktop.
|
||||||
|
|
||||||
|
|
@ -12,36 +12,31 @@
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
#include "imgui_impl_wgpu.h"
|
#include "imgui_impl_wgpu.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#include <emscripten/html5_webgpu.h>
|
#include <emscripten/html5_webgpu.h>
|
||||||
|
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||||
#else
|
#else
|
||||||
#include <webgpu/webgpu_glfw.h>
|
#include <webgpu/webgpu_glfw.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
#include <webgpu/webgpu_cpp.h>
|
#include <webgpu/webgpu_cpp.h>
|
||||||
|
|
||||||
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
// Data
|
||||||
#ifdef __EMSCRIPTEN__
|
static WGPUInstance wgpu_instance = nullptr;
|
||||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
static WGPUDevice wgpu_device = nullptr;
|
||||||
#endif
|
static WGPUSurface wgpu_surface = nullptr;
|
||||||
|
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
|
||||||
// Global WebGPU required states
|
static WGPUSwapChain wgpu_swap_chain = nullptr;
|
||||||
static WGPUInstance wgpu_instance = nullptr;
|
static int wgpu_surface_width = 1280;
|
||||||
static WGPUDevice wgpu_device = nullptr;
|
static int wgpu_surface_height = 800;
|
||||||
static WGPUSurface wgpu_surface = nullptr;
|
|
||||||
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
|
|
||||||
static WGPUSwapChain wgpu_swap_chain = nullptr;
|
|
||||||
static int wgpu_swap_chain_width = 1280;
|
|
||||||
static int wgpu_swap_chain_height = 800;
|
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
static bool InitWGPU(GLFWwindow* window);
|
static bool InitWGPU(GLFWwindow* window);
|
||||||
static void CreateSwapChain(int width, int height);
|
|
||||||
|
|
||||||
static void glfw_error_callback(int error, const char* description)
|
static void glfw_error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
|
|
@ -62,6 +57,21 @@ static void wgpu_error_callback(WGPUErrorType error_type, const char* message, v
|
||||||
printf("%s error: %s\n", error_type_lbl, message);
|
printf("%s error: %s\n", error_type_lbl, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ResizeSurface(int width, int height)
|
||||||
|
{
|
||||||
|
if (wgpu_swap_chain)
|
||||||
|
wgpuSwapChainRelease(wgpu_swap_chain);
|
||||||
|
wgpu_surface_width = width;
|
||||||
|
wgpu_surface_height = height;
|
||||||
|
WGPUSwapChainDescriptor swap_chain_desc = {};
|
||||||
|
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||||
|
swap_chain_desc.format = wgpu_preferred_fmt;
|
||||||
|
swap_chain_desc.width = width;
|
||||||
|
swap_chain_desc.height = height;
|
||||||
|
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
|
||||||
|
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
|
||||||
|
}
|
||||||
|
|
||||||
// Main code
|
// Main code
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
|
|
@ -72,19 +82,23 @@ int main(int, char**)
|
||||||
// Make sure GLFW does not initialize any graphics context.
|
// Make sure GLFW does not initialize any graphics context.
|
||||||
// This needs to be done explicitly later.
|
// This needs to be done explicitly later.
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
|
|
||||||
|
// Create window
|
||||||
|
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||||
|
wgpu_surface_width *= main_scale;
|
||||||
|
wgpu_surface_height *= main_scale;
|
||||||
|
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
|
||||||
if (window == nullptr)
|
if (window == nullptr)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Initialize the WebGPU environment
|
// Initialize the WebGPU environment
|
||||||
if (!InitWGPU(window))
|
if (!InitWGPU(window))
|
||||||
{
|
{
|
||||||
if (window)
|
glfwDestroyWindow(window);
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height);
|
ResizeSurface(wgpu_surface_width, wgpu_surface_height);
|
||||||
glfwShowWindow(window);
|
glfwShowWindow(window);
|
||||||
|
|
||||||
// Setup Dear ImGui context
|
// Setup Dear ImGui context
|
||||||
|
|
@ -99,6 +113,11 @@ int main(int, char**)
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
//ImGui::StyleColorsLight();
|
//ImGui::StyleColorsLight();
|
||||||
|
|
||||||
|
// Setup scaling
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||||
|
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
|
||||||
|
|
||||||
// Setup Platform/Renderer backends
|
// Setup Platform/Renderer backends
|
||||||
ImGui_ImplGlfw_InitForOther(window, true);
|
ImGui_ImplGlfw_InitForOther(window, true);
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
|
|
@ -118,15 +137,14 @@ int main(int, char**)
|
||||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
||||||
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
|
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
|
||||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||||
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
|
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
|
||||||
//io.Fonts->AddFontDefault();
|
|
||||||
//style.FontSizeBase = 20.0f;
|
//style.FontSizeBase = 20.0f;
|
||||||
|
//io.Fonts->AddFontDefault();
|
||||||
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||||
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
|
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
|
||||||
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
|
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
|
||||||
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
|
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
|
||||||
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
|
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
|
||||||
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf");
|
|
||||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
|
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
|
||||||
//IM_ASSERT(font != nullptr);
|
//IM_ASSERT(font != nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -161,12 +179,8 @@ int main(int, char**)
|
||||||
// React to changes in screen size
|
// React to changes in screen size
|
||||||
int width, height;
|
int width, height;
|
||||||
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
|
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
|
||||||
if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height)
|
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||||
{
|
ResizeSurface(width, height);
|
||||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
|
||||||
CreateSwapChain(width, height);
|
|
||||||
ImGui_ImplWGPU_CreateDeviceObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the Dear ImGui frame
|
// Start the Dear ImGui frame
|
||||||
ImGui_ImplWGPU_NewFrame();
|
ImGui_ImplWGPU_NewFrame();
|
||||||
|
|
@ -239,8 +253,8 @@ int main(int, char**)
|
||||||
|
|
||||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||||
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
|
WGPUQueue wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
|
||||||
wgpuQueueSubmit(queue, 1, &cmd_buffer);
|
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
wgpuSwapChainPresent(wgpu_swap_chain);
|
wgpuSwapChainPresent(wgpu_swap_chain);
|
||||||
|
|
@ -272,21 +286,21 @@ static WGPUAdapter RequestAdapter(WGPUInstance instance)
|
||||||
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
|
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
|
||||||
{
|
{
|
||||||
if (status == WGPURequestAdapterStatus_Success)
|
if (status == WGPURequestAdapterStatus_Success)
|
||||||
*(WGPUAdapter*)(pUserData) = adapter;
|
*(WGPUAdapter*)pUserData = adapter;
|
||||||
else
|
else
|
||||||
printf("Could not get WebGPU adapter: %s\n", message);
|
printf("Could not get WebGPU adapter: %s\n", message);
|
||||||
};
|
};
|
||||||
WGPUAdapter adapter;
|
WGPUAdapter adapter;
|
||||||
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
|
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
static WGPUDevice RequestDevice(WGPUAdapter adapter)
|
||||||
{
|
{
|
||||||
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
|
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
|
||||||
{
|
{
|
||||||
if (status == WGPURequestDeviceStatus_Success)
|
if (status == WGPURequestDeviceStatus_Success)
|
||||||
*(WGPUDevice*)(pUserData) = device;
|
*(WGPUDevice*)pUserData = device;
|
||||||
else
|
else
|
||||||
printf("Could not get WebGPU device: %s\n", message);
|
printf("Could not get WebGPU device: %s\n", message);
|
||||||
};
|
};
|
||||||
|
|
@ -304,48 +318,31 @@ static bool InitWGPU(GLFWwindow* window)
|
||||||
wgpu_device = emscripten_webgpu_get_device();
|
wgpu_device = emscripten_webgpu_get_device();
|
||||||
if (!wgpu_device)
|
if (!wgpu_device)
|
||||||
return false;
|
return false;
|
||||||
#else
|
|
||||||
WGPUAdapter adapter = RequestAdapter(instance.Get());
|
|
||||||
if (!adapter)
|
|
||||||
return false;
|
|
||||||
wgpu_device = RequestDevice(adapter);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {};
|
||||||
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
canvas_desc.selector = "#canvas";
|
||||||
html_surface_desc.selector = "#canvas";
|
|
||||||
wgpu::SurfaceDescriptor surface_desc = {};
|
wgpu::SurfaceDescriptor surface_desc = {};
|
||||||
surface_desc.nextInChain = &html_surface_desc;
|
surface_desc.nextInChain = &canvas_desc;
|
||||||
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
|
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
|
||||||
|
|
||||||
wgpu::Adapter adapter = {};
|
wgpu::Adapter adapter = {};
|
||||||
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
|
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
|
||||||
#else
|
#else
|
||||||
|
WGPUAdapter adapter = RequestAdapter(instance.Get());
|
||||||
|
if (!adapter)
|
||||||
|
return false;
|
||||||
|
wgpu_device = RequestDevice(adapter);
|
||||||
|
|
||||||
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
|
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
|
||||||
if (!surface)
|
if (!surface)
|
||||||
return false;
|
return false;
|
||||||
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
|
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Moving Dawn objects into WGPU handles
|
||||||
wgpu_instance = instance.MoveToCHandle();
|
wgpu_instance = instance.MoveToCHandle();
|
||||||
wgpu_surface = surface.MoveToCHandle();
|
wgpu_surface = surface.MoveToCHandle();
|
||||||
|
|
||||||
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
|
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreateSwapChain(int width, int height)
|
|
||||||
{
|
|
||||||
if (wgpu_swap_chain)
|
|
||||||
wgpuSwapChainRelease(wgpu_swap_chain);
|
|
||||||
wgpu_swap_chain_width = width;
|
|
||||||
wgpu_swap_chain_height = height;
|
|
||||||
WGPUSwapChainDescriptor swap_chain_desc = {};
|
|
||||||
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
|
||||||
swap_chain_desc.format = wgpu_preferred_fmt;
|
|
||||||
swap_chain_desc.width = width;
|
|
||||||
swap_chain_desc.height = height;
|
|
||||||
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
|
|
||||||
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ int main(int, char**)
|
||||||
bool CreateDeviceD3D(HWND hWnd)
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
{
|
{
|
||||||
// Setup swap chain
|
// Setup swap chain
|
||||||
|
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
|
||||||
DXGI_SWAP_CHAIN_DESC sd;
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
ZeroMemory(&sd, sizeof(sd));
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
sd.BufferCount = 2;
|
sd.BufferCount = 2;
|
||||||
|
|
@ -261,7 +262,10 @@ bool CreateDeviceD3D(HWND hWnd)
|
||||||
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
||||||
IDXGIFactory* pSwapChainFactory;
|
IDXGIFactory* pSwapChainFactory;
|
||||||
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
||||||
|
{
|
||||||
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
pSwapChainFactory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
CreateRenderTarget();
|
CreateRenderTarget();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ int main(int, char**)
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_GetWindowProperties(window);
|
SDL_PropertiesID props = SDL_GetWindowProperties(window);
|
||||||
HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||||
|
|
||||||
// Initialize Direct3D
|
// Initialize Direct3D
|
||||||
if (!CreateDeviceD3D(hwnd))
|
if (!CreateDeviceD3D(hwnd))
|
||||||
|
|
@ -225,6 +225,7 @@ int main(int, char**)
|
||||||
bool CreateDeviceD3D(HWND hWnd)
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
{
|
{
|
||||||
// Setup swap chain
|
// Setup swap chain
|
||||||
|
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
|
||||||
DXGI_SWAP_CHAIN_DESC sd;
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
ZeroMemory(&sd, sizeof(sd));
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
sd.BufferCount = 2;
|
sd.BufferCount = 2;
|
||||||
|
|
@ -256,7 +257,10 @@ bool CreateDeviceD3D(HWND hWnd)
|
||||||
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
||||||
IDXGIFactory* pSwapChainFactory;
|
IDXGIFactory* pSwapChainFactory;
|
||||||
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
||||||
|
{
|
||||||
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
pSwapChainFactory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
CreateRenderTarget();
|
CreateRenderTarget();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -491,7 +491,7 @@ int main(int, char**)
|
||||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_height, fb_height, g_MinImageCount, 0);
|
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
|
||||||
g_MainWindowData.FrameIndex = 0;
|
g_MainWindowData.FrameIndex = 0;
|
||||||
g_SwapChainRebuild = false;
|
g_SwapChainRebuild = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ int main(int, char**)
|
||||||
bool CreateDeviceD3D(HWND hWnd)
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
{
|
{
|
||||||
// Setup swap chain
|
// Setup swap chain
|
||||||
|
// This is a basic setup. Optimally could use handle fullscreen mode differently. See #8979 for suggestions.
|
||||||
DXGI_SWAP_CHAIN_DESC sd;
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
ZeroMemory(&sd, sizeof(sd));
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
sd.BufferCount = 2;
|
sd.BufferCount = 2;
|
||||||
|
|
@ -246,7 +247,10 @@ bool CreateDeviceD3D(HWND hWnd)
|
||||||
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
||||||
IDXGIFactory* pSwapChainFactory;
|
IDXGIFactory* pSwapChainFactory;
|
||||||
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
||||||
|
{
|
||||||
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
pSwapChainFactory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
CreateRenderTarget();
|
CreateRenderTarget();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,7 @@ int main(int, char**)
|
||||||
bool CreateDeviceD3D(HWND hWnd)
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
{
|
{
|
||||||
// Setup swap chain
|
// Setup swap chain
|
||||||
|
// This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions.
|
||||||
DXGI_SWAP_CHAIN_DESC sd;
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
ZeroMemory(&sd, sizeof(sd));
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
sd.BufferCount = 2;
|
sd.BufferCount = 2;
|
||||||
|
|
@ -250,7 +251,10 @@ bool CreateDeviceD3D(HWND hWnd)
|
||||||
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
// - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates.
|
||||||
IDXGIFactory* pSwapChainFactory;
|
IDXGIFactory* pSwapChainFactory;
|
||||||
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory))))
|
||||||
|
{
|
||||||
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
pSwapChainFactory->Release();
|
||||||
|
}
|
||||||
|
|
||||||
CreateRenderTarget();
|
CreateRenderTarget();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,7 @@ int main(int, char**)
|
||||||
bool CreateDeviceD3D(HWND hWnd)
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
{
|
{
|
||||||
// Setup swap chain
|
// Setup swap chain
|
||||||
|
// This is a basic setup. Optimally could handle fullscreen mode differently. See #8979 for suggestions.
|
||||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||||
{
|
{
|
||||||
ZeroMemory(&sd, sizeof(sd));
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
|
|
@ -545,7 +546,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||||
g_pSwapChain->GetDesc1(&desc);
|
g_pSwapChain->GetDesc1(&desc);
|
||||||
HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), desc.Format, desc.Flags);
|
HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), desc.Format, desc.Flags);
|
||||||
assert(SUCCEEDED(result) && "Failed to resize swapchain.");
|
IM_ASSERT(SUCCEEDED(result) && "Failed to resize swapchain.");
|
||||||
CreateRenderTarget();
|
CreateRenderTarget();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@
|
||||||
|
|
||||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||||
|
// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience.
|
||||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||||
//#define IMGUI_ENABLE_FREETYPE
|
//#define IMGUI_ENABLE_FREETYPE
|
||||||
|
|
||||||
|
|
|
||||||
82
imgui.cpp
82
imgui.cpp
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (main code and documentation)
|
// (main code and documentation)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
|
|
@ -400,6 +400,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||||
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
||||||
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
||||||
|
|
||||||
|
- 2025/10/14 (1.92.4) - TreeNode, Selectable, Clipper: commented out legacy names which were obsoleted in 1.89.7 (July 2023) and 1.89.9 (Sept 2023);
|
||||||
|
- ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap
|
||||||
|
- ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap
|
||||||
|
- ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex()
|
||||||
- 2025/09/22 (1.92.4) - Viewports: renamed io.ConfigViewportPlatformFocusSetsImGuiFocus to io.ConfigViewportsPlatformFocusSetsImGuiFocus. Was a typo in the first place. (#6299, #6462)
|
- 2025/09/22 (1.92.4) - Viewports: renamed io.ConfigViewportPlatformFocusSetsImGuiFocus to io.ConfigViewportsPlatformFocusSetsImGuiFocus. Was a typo in the first place. (#6299, #6462)
|
||||||
- 2025/08/08 (1.92.2) - Backends: SDL_GPU3: Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
|
- 2025/08/08 (1.92.2) - Backends: SDL_GPU3: Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988)
|
||||||
- 2025/07/31 (1.92.2) - Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. Kept inline redirection enum (will obsolete).
|
- 2025/07/31 (1.92.2) - Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. Kept inline redirection enum (will obsolete).
|
||||||
|
|
@ -3767,6 +3771,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||||
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
|
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
|
||||||
case ImGuiCol_TreeLines: return "TreeLines";
|
case ImGuiCol_TreeLines: return "TreeLines";
|
||||||
case ImGuiCol_DragDropTarget: return "DragDropTarget";
|
case ImGuiCol_DragDropTarget: return "DragDropTarget";
|
||||||
|
case ImGuiCol_UnsavedMarker: return "UnsavedMarker";
|
||||||
case ImGuiCol_NavCursor: return "NavCursor";
|
case ImGuiCol_NavCursor: return "NavCursor";
|
||||||
case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
|
case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
|
||||||
case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
|
case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
|
||||||
|
|
@ -4747,7 +4752,8 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||||
|
|
||||||
// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
|
// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
|
||||||
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
|
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
|
||||||
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
|
||||||
|
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
||||||
|
|
||||||
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
|
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||||
|
|
@ -7551,7 +7557,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
|
||||||
marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
|
marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
|
||||||
if (marker_pos.x > layout_r.Min.x)
|
if (marker_pos.x > layout_r.Min.x)
|
||||||
{
|
{
|
||||||
RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
|
RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_UnsavedMarker));
|
||||||
clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));
|
clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7572,7 +7578,7 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
|
||||||
}
|
}
|
||||||
if (parent_window && (flags & ImGuiWindowFlags_Popup))
|
if (parent_window && (flags & ImGuiWindowFlags_Popup))
|
||||||
window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
|
window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
|
||||||
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) // FIXME: simply use _NoTitleBar ?
|
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip))) // FIXME: simply use _NoTitleBar ?
|
||||||
window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
|
window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
|
||||||
while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened)
|
while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened)
|
||||||
{
|
{
|
||||||
|
|
@ -7717,7 +7723,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||||
|
|
||||||
// Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
|
// Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
|
||||||
ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow : g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window;
|
ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow : g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window;
|
||||||
ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
|
ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) ? parent_window_in_stack : NULL) : window->ParentWindow;
|
||||||
IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
|
IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
|
||||||
|
|
||||||
// We allow window memory to be compacted so recreate the base stack when needed.
|
// We allow window memory to be compacted so recreate the base stack when needed.
|
||||||
|
|
@ -9997,7 +10003,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
|
||||||
routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
|
routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
|
||||||
routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry
|
routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry
|
||||||
routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
|
routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
|
||||||
routing_entry->RoutingNextScore = 255;
|
routing_entry->RoutingNextScore = 0;
|
||||||
if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
|
if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
|
||||||
continue;
|
continue;
|
||||||
rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer
|
rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer
|
||||||
|
|
@ -10066,23 +10072,24 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
|
||||||
return routing_data;
|
return routing_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current score encoding (lower is highest priority):
|
// Current score encoding
|
||||||
// - 0: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive
|
// - 0: Never route
|
||||||
// - 1: ImGuiInputFlags_ActiveItem or ImGuiInputFlags_RouteFocused (if item active)
|
// - 1: ImGuiInputFlags_RouteGlobal (lower priority)
|
||||||
// - 2: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused
|
// - 100..199: ImGuiInputFlags_RouteFocused (if window in focus-stack)
|
||||||
// - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack)
|
// 200: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused
|
||||||
// - 254: ImGuiInputFlags_RouteGlobal
|
// 300: ImGuiInputFlags_RouteActive or ImGuiInputFlags_RouteFocused (if item active)
|
||||||
// - 255: never route
|
// 400: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive
|
||||||
|
// - 500..599: ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteOverActive (if window in focus-stack) (higher priority)
|
||||||
// 'flags' should include an explicit routing policy
|
// 'flags' should include an explicit routing policy
|
||||||
static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
|
static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (flags & ImGuiInputFlags_RouteFocused)
|
if (flags & ImGuiInputFlags_RouteFocused)
|
||||||
{
|
{
|
||||||
// ActiveID gets top priority
|
// ActiveID gets high priority
|
||||||
// (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it)
|
// (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it)
|
||||||
if (owner_id != 0 && g.ActiveId == owner_id)
|
if (owner_id != 0 && g.ActiveId == owner_id)
|
||||||
return 1;
|
return 300;
|
||||||
|
|
||||||
// Score based on distance to focused window (lower is better)
|
// Score based on distance to focused window (lower is better)
|
||||||
// Assuming both windows are submitting a routing request,
|
// Assuming both windows are submitting a routing request,
|
||||||
|
|
@ -10092,25 +10099,32 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput
|
||||||
// - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score.
|
// - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score.
|
||||||
// This essentially follow the window->ParentWindowForFocusRoute chain.
|
// This essentially follow the window->ParentWindowForFocusRoute chain.
|
||||||
if (focus_scope_id == 0)
|
if (focus_scope_id == 0)
|
||||||
return 255;
|
return 0;
|
||||||
for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++)
|
for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++)
|
||||||
if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
|
if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
|
||||||
return 3 + index_in_focus_path;
|
{
|
||||||
return 255;
|
if (flags & ImGuiInputFlags_RouteOverActive) // && g.ActiveId != 0 && g.ActiveId != owner_id)
|
||||||
|
return 599 - index_in_focus_path;
|
||||||
|
else
|
||||||
|
return 199 - index_in_focus_path;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (flags & ImGuiInputFlags_RouteActive)
|
else if (flags & ImGuiInputFlags_RouteActive)
|
||||||
{
|
{
|
||||||
if (owner_id != 0 && g.ActiveId == owner_id)
|
if (owner_id != 0 && g.ActiveId == owner_id)
|
||||||
return 1;
|
return 300;
|
||||||
return 255;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (flags & ImGuiInputFlags_RouteGlobal)
|
else if (flags & ImGuiInputFlags_RouteGlobal)
|
||||||
{
|
{
|
||||||
if (flags & ImGuiInputFlags_RouteOverActive)
|
if (flags & ImGuiInputFlags_RouteOverActive)
|
||||||
return 0;
|
return 400;
|
||||||
|
if (owner_id != 0 && g.ActiveId == owner_id)
|
||||||
|
return 300;
|
||||||
if (flags & ImGuiInputFlags_RouteOverFocused)
|
if (flags & ImGuiInputFlags_RouteOverFocused)
|
||||||
return 2;
|
return 200;
|
||||||
return 254;
|
return 1;
|
||||||
}
|
}
|
||||||
IM_ASSERT(0);
|
IM_ASSERT(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -10150,8 +10164,10 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I
|
||||||
else
|
else
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used
|
||||||
IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
|
IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
|
||||||
if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused))
|
if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteUnlessBgFocused))
|
||||||
IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
|
IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
|
||||||
|
if (flags & ImGuiInputFlags_RouteOverActive)
|
||||||
|
IM_ASSERT(flags & (ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteFocused));
|
||||||
|
|
||||||
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
|
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
|
||||||
key_chord = FixupKeyChord(key_chord);
|
key_chord = FixupKeyChord(key_chord);
|
||||||
|
|
@ -10206,17 +10222,17 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I
|
||||||
|
|
||||||
const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
|
const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
|
||||||
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score);
|
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score);
|
||||||
if (score == 255)
|
if (score == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Submit routing for NEXT frame (assuming score is sufficient)
|
// Submit routing for NEXT frame (assuming score is sufficient)
|
||||||
// FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <).
|
// FIXME: Could expose a way to use a "serve last" policy for same score resolution (using >= instead of >).
|
||||||
ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
|
ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
|
||||||
//const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore);
|
//const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score >= routing_data->RoutingNextScore) : (score > routing_data->RoutingNextScore);
|
||||||
if (score < routing_data->RoutingNextScore)
|
if (score > routing_data->RoutingNextScore)
|
||||||
{
|
{
|
||||||
routing_data->RoutingNext = owner_id;
|
routing_data->RoutingNext = owner_id;
|
||||||
routing_data->RoutingNextScore = (ImU8)score;
|
routing_data->RoutingNextScore = (ImU16)score;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return routing state for CURRENT frame
|
// Return routing state for CURRENT frame
|
||||||
|
|
@ -12181,6 +12197,7 @@ void ImGui::BeginGroup()
|
||||||
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
||||||
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
|
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
|
||||||
group_data.BackupIsSameLine = window->DC.IsSameLine;
|
group_data.BackupIsSameLine = window->DC.IsSameLine;
|
||||||
|
group_data.BackupActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame;
|
||||||
group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
|
group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
|
||||||
group_data.EmitItem = true;
|
group_data.EmitItem = true;
|
||||||
|
|
||||||
|
|
@ -12245,7 +12262,7 @@ void ImGui::EndGroup()
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
|
||||||
|
|
||||||
// Forward Edited flag
|
// Forward Edited flag
|
||||||
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
|
if (g.ActiveIdHasBeenEditedThisFrame && !group_data.BackupActiveIdHasBeenEditedThisFrame)
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||||
|
|
||||||
// Forward Deactivated flag
|
// Forward Deactivated flag
|
||||||
|
|
@ -14941,7 +14958,7 @@ static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window)
|
||||||
FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
|
FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
|
||||||
IM_ASSERT(g.NavWindow != NULL);
|
IM_ASSERT(g.NavWindow != NULL);
|
||||||
apply_focus_window = g.NavWindow;
|
apply_focus_window = g.NavWindow;
|
||||||
if (apply_focus_window->NavLastIds[0] == 0)
|
if (apply_focus_window->NavLastIds[0] == 0) // FIXME: This is the equivalent of the 'if (g.NavId == 0) { NavInitWindow() }' in DockNodeUpdateTabBar().
|
||||||
NavInitWindow(apply_focus_window, false);
|
NavInitWindow(apply_focus_window, false);
|
||||||
|
|
||||||
// If the window has ONLY a menu layer (no main layer), select it directly
|
// If the window has ONLY a menu layer (no main layer), select it directly
|
||||||
|
|
@ -19354,7 +19371,8 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
||||||
if (tab->Window)
|
if (tab->Window)
|
||||||
{
|
{
|
||||||
FocusWindow(tab->Window);
|
FocusWindow(tab->Window);
|
||||||
NavInitWindow(tab->Window, false);
|
if (g.NavId == 0) // only init if FocusWindow() didn't restore anything.
|
||||||
|
NavInitWindow(tab->Window, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndTabBar();
|
EndTabBar();
|
||||||
|
|
|
||||||
50
imgui.h
50
imgui.h
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (headers)
|
// (headers)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
|
|
@ -28,8 +28,8 @@
|
||||||
|
|
||||||
// Library Version
|
// Library Version
|
||||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||||
#define IMGUI_VERSION "1.92.4 WIP"
|
#define IMGUI_VERSION "1.92.5 WIP"
|
||||||
#define IMGUI_VERSION_NUM 19234
|
#define IMGUI_VERSION_NUM 19242
|
||||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||||
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
|
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
|
||||||
|
|
@ -956,18 +956,24 @@ namespace ImGui
|
||||||
IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
|
IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
|
||||||
|
|
||||||
// Docking
|
// Docking
|
||||||
// [BETA API] Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
|
// - Read https://github.com/ocornut/imgui/wiki/Docking for details.
|
||||||
// Note: You can use most Docking facilities without calling any API. You DO NOT need to call DockSpace() to use Docking!
|
// - Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
|
||||||
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
|
// - You can use most Docking facilities without calling any API. You don't necessarily need to call a DockSpaceXXX function to use Docking!
|
||||||
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
|
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
|
||||||
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
|
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
|
||||||
// About dockspaces:
|
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
|
||||||
// - Use DockSpaceOverViewport() to create a window covering the screen or a specific viewport + a dockspace inside it.
|
// - Dockspaces:
|
||||||
// This is often used with ImGuiDockNodeFlags_PassthruCentralNode to make it transparent.
|
// - If you want to dock windows into the edge of your screen, most application can simply call DockSpaceOverViewport():
|
||||||
// - Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details.
|
// e.g. ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport.
|
||||||
// - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame!
|
// or: ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
|
||||||
// - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
|
// - A dockspace is an explicit dock node within an existing window.
|
||||||
// e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
|
// - DockSpaceOverViewport() basically creates an invisible window covering a viewport, and submit a DockSpace() into it.
|
||||||
|
// - IMPORTANT: Dockspaces need to be submitted _before_ any window they can host. Submit them early in your frame!
|
||||||
|
// - IMPORTANT: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
|
||||||
|
// If you have e.g. multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
|
||||||
|
// - Programmatic docking:
|
||||||
|
// - There is no public API yet other than the very limited SetNextWindowDockID() function. Sorry for that!
|
||||||
|
// - Read https://github.com/ocornut/imgui/wiki/Docking for examples of how to use current internal API.
|
||||||
IMGUI_API ImGuiID DockSpace(ImGuiID dockspace_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
|
IMGUI_API ImGuiID DockSpace(ImGuiID dockspace_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
|
||||||
IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
|
IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
|
||||||
IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id
|
IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id
|
||||||
|
|
@ -1350,7 +1356,7 @@ enum ImGuiTreeNodeFlags_
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
|
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
|
||||||
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
|
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
|
||||||
ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
|
//ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1393,7 +1399,7 @@ enum ImGuiSelectableFlags_
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0
|
ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0
|
||||||
ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7
|
//ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1851,6 +1857,7 @@ enum ImGuiCol_
|
||||||
ImGuiCol_TextSelectedBg, // Selected text inside an InputText
|
ImGuiCol_TextSelectedBg, // Selected text inside an InputText
|
||||||
ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines
|
ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines
|
||||||
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
|
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
|
||||||
|
ImGuiCol_UnsavedMarker, // Unsaved Document marker (in window title and tabs)
|
||||||
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
|
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
|
||||||
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
|
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
|
||||||
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
|
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
|
||||||
|
|
@ -2977,7 +2984,7 @@ struct ImGuiListClipper
|
||||||
IMGUI_API void SeekCursorForItem(int item_index);
|
IMGUI_API void SeekCursorForItem(int item_index);
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9]
|
//inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9]
|
||||||
//inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6]
|
//inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6]
|
||||||
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
|
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3125,6 +3132,7 @@ enum ImGuiMultiSelectFlags_
|
||||||
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
|
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
|
||||||
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
|
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
|
||||||
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
|
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
|
||||||
|
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
|
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
|
||||||
|
|
@ -4137,7 +4145,7 @@ struct ImGuiPlatformIO
|
||||||
void* Platform_ClipboardUserData;
|
void* Platform_ClipboardUserData;
|
||||||
|
|
||||||
// Optional: Open link/folder/file in OS Shell
|
// Optional: Open link/folder/file in OS Shell
|
||||||
// (default to use ShellExecuteW() on Windows, system() on Linux/Mac)
|
// (default to use ShellExecuteW() on Windows, system() on Linux/Mac. expected to return false on failure, but some platforms may always return true)
|
||||||
bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path);
|
bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path);
|
||||||
void* Platform_OpenInShellUserData;
|
void* Platform_OpenInShellUserData;
|
||||||
|
|
||||||
|
|
@ -4228,8 +4236,8 @@ struct ImGuiPlatformIO
|
||||||
// Functions
|
// Functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown.
|
IMGUI_API void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown.
|
||||||
void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown.
|
IMGUI_API void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown.
|
||||||
};
|
};
|
||||||
|
|
||||||
// (Optional) This is required when enabling multi-viewport. Represent the bounds of each connected monitor/display and their DPI.
|
// (Optional) This is required when enabling multi-viewport. Represent the bounds of each connected monitor/display and their DPI.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (demo code)
|
// (demo code)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
|
|
@ -2731,6 +2731,10 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
|
||||||
{
|
{
|
||||||
HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data.");
|
HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data.");
|
||||||
|
|
||||||
|
ImGui::BulletText("Wiki page:");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextLinkOpenURL("imgui/wiki/Multi-Select", "https://github.com/ocornut/imgui/wiki/Multi-Select");
|
||||||
|
|
||||||
// Without any fancy API: manage single-selection yourself.
|
// Without any fancy API: manage single-selection yourself.
|
||||||
IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select");
|
IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select");
|
||||||
if (ImGui::TreeNode("Single-Select"))
|
if (ImGui::TreeNode("Single-Select"))
|
||||||
|
|
@ -3264,6 +3268,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect);
|
||||||
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectOnRightClick", &flags, ImGuiMultiSelectFlags_NoSelectOnRightClick);
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d);
|
||||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll);
|
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll);
|
||||||
|
|
@ -4879,15 +4884,18 @@ static void DemoWindowLayout()
|
||||||
|
|
||||||
ImGui::Checkbox("Decoration", &enable_extra_decorations);
|
ImGui::Checkbox("Decoration", &enable_extra_decorations);
|
||||||
|
|
||||||
|
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
|
||||||
|
enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
|
||||||
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("Track", &enable_track);
|
ImGui::Checkbox("Track", &enable_track);
|
||||||
ImGui::PushItemWidth(100);
|
|
||||||
ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
|
|
||||||
|
|
||||||
bool scroll_to_off = ImGui::Button("Scroll Offset");
|
bool scroll_to_off = ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
|
||||||
ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
|
ImGui::SameLine();
|
||||||
|
scroll_to_off |= ImGui::Button("Scroll Offset");
|
||||||
|
|
||||||
bool scroll_to_pos = ImGui::Button("Scroll To Pos");
|
bool scroll_to_pos = ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
|
||||||
ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
|
ImGui::SameLine();
|
||||||
|
scroll_to_pos |= ImGui::Button("Scroll To Pos");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
if (scroll_to_off || scroll_to_pos)
|
if (scroll_to_off || scroll_to_pos)
|
||||||
|
|
@ -10245,37 +10253,27 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||||
// [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
|
// [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Demonstrate using DockSpace() to create an explicit docking node within an existing window.
|
// Demonstrate using DockSpace() to create an explicit docking node within an existing window, with various options.
|
||||||
// Note: You can use most Docking facilities without calling any API. You DO NOT need to call DockSpace() to use Docking!
|
// THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace().
|
||||||
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
|
// MOST REGULAR APPLICATIONS WHO WANT TO ALLOW DOCKING WINDOWS ON THE EDGE OF YOUR SCREEN CAN SIMPLY USE:
|
||||||
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
|
// ImGui::NewFrame();
|
||||||
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
|
// ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport
|
||||||
// About dockspaces:
|
// OR:
|
||||||
// - Use DockSpace() to create an explicit dock node _within_ an existing window.
|
// ImGui::NewFrame();
|
||||||
// - Use DockSpaceOverViewport() to create an explicit dock node covering the screen or a specific viewport.
|
// ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
|
||||||
// This is often used with ImGuiDockNodeFlags_PassthruCentralNode.
|
// Read https://github.com/ocornut/imgui/wiki/Docking for details.
|
||||||
// - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! (*)
|
// The reasons we do not use DockSpaceOverViewport() in this demo is because:
|
||||||
// - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
|
// - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false)
|
||||||
// e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
|
// which is mostly to showcase the idea that DockSpace() may be submitted anywhere.
|
||||||
// (*) because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node,
|
// - (2) we allow the host window to have padding (when opt_padding == true)
|
||||||
// because that window is submitted as part of the part of the NewFrame() call. An easy workaround is that you can create
|
// - (3) we expose many flags and need a way to have them visible.
|
||||||
// your own implicit "Debug##2" window after calling DockSpace() and leave it in the window stack for anyone to use.
|
// - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport()
|
||||||
|
// in your code, but we don't here because we allow the window to be floating)
|
||||||
void ShowExampleAppDockSpace(bool* p_open)
|
void ShowExampleAppDockSpace(bool* p_open)
|
||||||
{
|
{
|
||||||
// READ THIS !!!
|
|
||||||
// TL;DR; this demo is more complicated than what most users you would normally use.
|
// TL;DR; this demo is more complicated than what most users you would normally use.
|
||||||
// If we remove all options we are showcasing, this demo would become:
|
// If we remove all options we are showcasing, this demo would become a simple call to ImGui::DockSpaceOverViewport() !!
|
||||||
// void ShowExampleAppDockSpace()
|
|
||||||
// {
|
|
||||||
// ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
|
|
||||||
// }
|
|
||||||
// In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below!
|
|
||||||
// In this specific demo, we are not using DockSpaceOverViewport() because:
|
// In this specific demo, we are not using DockSpaceOverViewport() because:
|
||||||
// - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false)
|
|
||||||
// - (2) we allow the host window to have padding (when opt_padding == true)
|
|
||||||
// - (3) we expose many flags and need a way to have them visible.
|
|
||||||
// - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport()
|
|
||||||
// in your code, but we don't here because we allow the window to be floating)
|
|
||||||
|
|
||||||
static bool opt_fullscreen = true;
|
static bool opt_fullscreen = true;
|
||||||
static bool opt_padding = false;
|
static bool opt_padding = false;
|
||||||
|
|
@ -10320,6 +10318,8 @@ void ShowExampleAppDockSpace(bool* p_open)
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
|
|
||||||
// Submit the DockSpace
|
// Submit the DockSpace
|
||||||
|
// REMINDER: THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace()!
|
||||||
|
// MOST REGULAR APPLICATIONS WILL SIMPLY WANT TO CALL DockSpaceOverViewport(). READ COMMENTS ABOVE.
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
||||||
{
|
{
|
||||||
|
|
@ -10331,6 +10331,7 @@ void ShowExampleAppDockSpace(bool* p_open)
|
||||||
ShowDockingDisabledMessage();
|
ShowDockingDisabledMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show demo options and help
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenu("Options"))
|
if (ImGui::BeginMenu("Options"))
|
||||||
|
|
@ -10353,16 +10354,23 @@ void ShowExampleAppDockSpace(bool* p_open)
|
||||||
*p_open = false;
|
*p_open = false;
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
HelpMarker(
|
if (ImGui::BeginMenu("Help"))
|
||||||
"When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
|
{
|
||||||
"- Drag from window title bar or their tab to dock/undock." "\n"
|
ImGui::TextUnformatted(
|
||||||
"- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
|
"This demo has nothing to do with enabling docking!" "\n"
|
||||||
"- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
|
"This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n"
|
||||||
"- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)" "\n"
|
"Most application can simply call ImGui::DockSpaceOverViewport() and be done with it.");
|
||||||
"This demo app has nothing to do with enabling docking!" "\n\n"
|
ImGui::Separator();
|
||||||
"This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window." "\n\n"
|
ImGui::TextUnformatted("When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
|
||||||
"Read comments in ShowExampleAppDockSpace() for more details.");
|
"- Drag from window title bar or their tab to dock/undock." "\n"
|
||||||
|
"- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
|
||||||
|
"- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
|
||||||
|
"- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)");
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::TextUnformatted("More details:"); ImGui::Bullet(); ImGui::SameLine(); ImGui::TextLinkOpenURL("Docking Wiki page", "https://github.com/ocornut/imgui/wiki/Docking");
|
||||||
|
ImGui::BulletText("Read comments in ShowExampleAppDockSpace()");
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (drawing and font code)
|
// (drawing and font code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -242,6 +242,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
|
||||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||||
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
||||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||||
|
colors[ImGuiCol_UnsavedMarker] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||||
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||||
|
|
@ -309,6 +310,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
|
||||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
|
||||||
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
||||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||||
|
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
|
||||||
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
|
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||||
|
|
@ -377,6 +379,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
|
||||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||||
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
|
||||||
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
||||||
|
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
|
||||||
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
|
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
|
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (internal structures/api)
|
// (internal structures/api)
|
||||||
|
|
||||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||||
|
|
@ -1184,6 +1184,7 @@ struct IMGUI_API ImGuiGroupData
|
||||||
ImVec2 BackupCurrLineSize;
|
ImVec2 BackupCurrLineSize;
|
||||||
float BackupCurrLineTextBaseOffset;
|
float BackupCurrLineTextBaseOffset;
|
||||||
ImGuiID BackupActiveIdIsAlive;
|
ImGuiID BackupActiveIdIsAlive;
|
||||||
|
bool BackupActiveIdHasBeenEditedThisFrame;
|
||||||
bool BackupDeactivatedIdIsAlive;
|
bool BackupDeactivatedIdIsAlive;
|
||||||
bool BackupHoveredIdIsAlive;
|
bool BackupHoveredIdIsAlive;
|
||||||
bool BackupIsSameLine;
|
bool BackupIsSameLine;
|
||||||
|
|
@ -1578,12 +1579,12 @@ struct ImGuiKeyRoutingData
|
||||||
{
|
{
|
||||||
ImGuiKeyRoutingIndex NextEntryIndex;
|
ImGuiKeyRoutingIndex NextEntryIndex;
|
||||||
ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits.
|
ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits.
|
||||||
ImU8 RoutingCurrScore; // [DEBUG] For debug display
|
ImU16 RoutingCurrScore; // [DEBUG] For debug display
|
||||||
ImU8 RoutingNextScore; // Lower is better (0: perfect score)
|
ImU16 RoutingNextScore; // Lower is better (0: perfect score)
|
||||||
ImGuiID RoutingCurr;
|
ImGuiID RoutingCurr;
|
||||||
ImGuiID RoutingNext;
|
ImGuiID RoutingNext;
|
||||||
|
|
||||||
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; }
|
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 0; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching.
|
// Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching.
|
||||||
|
|
@ -2511,7 +2512,7 @@ struct ImGuiContext
|
||||||
float NavHighlightActivatedTimer;
|
float NavHighlightActivatedTimer;
|
||||||
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
|
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
|
||||||
ImGuiActivateFlags NavNextActivateFlags;
|
ImGuiActivateFlags NavNextActivateFlags;
|
||||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
|
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
|
||||||
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
|
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
|
||||||
ImS8 NavCursorHideFrames;
|
ImS8 NavCursorHideFrames;
|
||||||
//ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606.
|
//ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606.
|
||||||
|
|
@ -2691,7 +2692,7 @@ struct ImGuiContext
|
||||||
ImGuiWindow* LogWindow;
|
ImGuiWindow* LogWindow;
|
||||||
ImFileHandle LogFile; // If != NULL log to stdout/ file
|
ImFileHandle LogFile; // If != NULL log to stdout/ file
|
||||||
ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
|
ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
|
||||||
const char* LogNextPrefix;
|
const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully!
|
||||||
const char* LogNextSuffix;
|
const char* LogNextSuffix;
|
||||||
float LogLinePosY;
|
float LogLinePosY;
|
||||||
bool LogLineFirstItem;
|
bool LogLineFirstItem;
|
||||||
|
|
@ -3278,6 +3279,7 @@ struct IMGUI_API ImGuiTable
|
||||||
// sizeof() ~ 136 bytes.
|
// sizeof() ~ 136 bytes.
|
||||||
struct IMGUI_API ImGuiTableTempData
|
struct IMGUI_API ImGuiTableTempData
|
||||||
{
|
{
|
||||||
|
ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID.
|
||||||
int TableIndex; // Index in g.Tables.Buf[] pool
|
int TableIndex; // Index in g.Tables.Buf[] pool
|
||||||
float LastTimeActive; // Last timestamp this structure was used
|
float LastTimeActive; // Last timestamp this structure was used
|
||||||
float AngledHeadersExtraWidth; // Used in EndTable()
|
float AngledHeadersExtraWidth; // Used in EndTable()
|
||||||
|
|
@ -4219,7 +4221,7 @@ extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI
|
||||||
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
|
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
|
||||||
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
|
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
|
||||||
#else
|
#else
|
||||||
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
|
#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) ((void)0)
|
||||||
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)
|
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (tables and columns code)
|
// (tables and columns code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -464,6 +464,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||||
table->HostIndentX = inner_window->DC.Indent.x;
|
table->HostIndentX = inner_window->DC.Indent.x;
|
||||||
table->HostClipRect = inner_window->ClipRect;
|
table->HostClipRect = inner_window->ClipRect;
|
||||||
table->HostSkipItems = inner_window->SkipItems;
|
table->HostSkipItems = inner_window->SkipItems;
|
||||||
|
temp_data->WindowID = inner_window->ID;
|
||||||
temp_data->HostBackupWorkRect = inner_window->WorkRect;
|
temp_data->HostBackupWorkRect = inner_window->WorkRect;
|
||||||
temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
||||||
temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
||||||
|
|
@ -1366,7 +1367,7 @@ void ImGui::EndTable()
|
||||||
ImGuiWindow* inner_window = table->InnerWindow;
|
ImGuiWindow* inner_window = table->InnerWindow;
|
||||||
ImGuiWindow* outer_window = table->OuterWindow;
|
ImGuiWindow* outer_window = table->OuterWindow;
|
||||||
ImGuiTableTempData* temp_data = table->TempData;
|
ImGuiTableTempData* temp_data = table->TempData;
|
||||||
IM_ASSERT(inner_window == g.CurrentWindow);
|
IM_ASSERT(inner_window == g.CurrentWindow && inner_window->ID == temp_data->WindowID);
|
||||||
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
|
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
|
||||||
|
|
||||||
if (table->IsInsideRow)
|
if (table->IsInsideRow)
|
||||||
|
|
@ -1559,7 +1560,7 @@ void ImGui::EndTable()
|
||||||
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
|
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
|
||||||
IM_ASSERT(g.TablesTempDataStacked > 0);
|
IM_ASSERT(g.TablesTempDataStacked > 0);
|
||||||
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
|
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
|
||||||
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
g.CurrentTable = temp_data && (temp_data->WindowID == outer_window->ID) ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
||||||
if (g.CurrentTable)
|
if (g.CurrentTable)
|
||||||
{
|
{
|
||||||
g.CurrentTable->TempData = temp_data;
|
g.CurrentTable->TempData = temp_data;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.92.4 WIP
|
// dear imgui, v1.92.5 WIP
|
||||||
// (widgets code)
|
// (widgets code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3947,6 +3947,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *ctx;
|
ImGuiContext& g = *ctx;
|
||||||
ImGuiInputTextState* obj = &g.InputTextState;
|
ImGuiInputTextState* obj = &g.InputTextState;
|
||||||
|
IM_ASSERT(text_end_display >= text_begin && text_end_display <= text_end);
|
||||||
return ImFontCalcTextSizeEx(g.Font, g.FontSize, FLT_MAX, obj->WrapWidth, text_begin, text_end_display, text_end, out_remaining, out_offset, flags);
|
return ImFontCalcTextSizeEx(g.Font, g.FontSize, FLT_MAX, obj->WrapWidth, text_begin, text_end_display, text_end, out_remaining, out_offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4147,21 +4148,23 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
|
||||||
obj->TextLen -= n;
|
obj->TextLen -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
|
static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
|
||||||
{
|
{
|
||||||
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||||
const int text_len = obj->TextLen;
|
const int text_len = obj->TextLen;
|
||||||
IM_ASSERT(pos <= text_len);
|
IM_ASSERT(pos <= text_len);
|
||||||
|
|
||||||
if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity))
|
// We support partial insertion (with a mod in stb_textedit.h)
|
||||||
return false;
|
const int avail = obj->BufCapacity - 1 - obj->TextLen;
|
||||||
|
if (!is_resizable && new_text_len > avail)
|
||||||
|
new_text_len = avail; // 0
|
||||||
|
if (new_text_len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Grow internal buffer if needed
|
// Grow internal buffer if needed
|
||||||
IM_ASSERT(obj->TextSrc == obj->TextA.Data);
|
IM_ASSERT(obj->TextSrc == obj->TextA.Data);
|
||||||
if (new_text_len + text_len + 1 > obj->TextA.Size)
|
if (text_len + new_text_len + 1 > obj->TextA.Size && is_resizable)
|
||||||
{
|
{
|
||||||
if (!is_resizable)
|
|
||||||
return false;
|
|
||||||
obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
|
obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
|
||||||
obj->TextSrc = obj->TextA.Data;
|
obj->TextSrc = obj->TextA.Data;
|
||||||
}
|
}
|
||||||
|
|
@ -4175,7 +4178,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
|
||||||
obj->TextLen += new_text_len;
|
obj->TextLen += new_text_len;
|
||||||
obj->TextA[obj->TextLen] = '\0';
|
obj->TextA[obj->TextLen] = '\0';
|
||||||
|
|
||||||
return true;
|
return new_text_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
|
// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
|
||||||
|
|
@ -4210,7 +4213,8 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st
|
||||||
state->cursor = state->select_start = state->select_end = 0;
|
state->cursor = state->select_start = state->select_end = 0;
|
||||||
if (text_len <= 0)
|
if (text_len <= 0)
|
||||||
return;
|
return;
|
||||||
if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len))
|
int text_len_inserted = ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len);
|
||||||
|
if (text_len_inserted > 0)
|
||||||
{
|
{
|
||||||
state->cursor = state->select_start = state->select_end = text_len;
|
state->cursor = state->select_start = state->select_end = text_len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
|
@ -4305,15 +4309,20 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||||
ImGuiContext& g = *Ctx;
|
ImGuiContext& g = *Ctx;
|
||||||
ImGuiInputTextState* obj = &g.InputTextState;
|
ImGuiInputTextState* obj = &g.InputTextState;
|
||||||
IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID);
|
IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID);
|
||||||
|
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||||
|
const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0;
|
||||||
|
int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
|
||||||
|
|
||||||
|
// We support partial insertion (with a mod in stb_textedit.h)
|
||||||
|
const int avail = BufSize - 1 - BufTextLen;
|
||||||
|
if (!is_resizable && new_text_len > avail)
|
||||||
|
new_text_len = avail; // 0
|
||||||
|
if (new_text_len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// Grow internal buffer if needed
|
// Grow internal buffer if needed
|
||||||
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly)
|
||||||
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
|
|
||||||
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0)
|
|
||||||
{
|
{
|
||||||
if (!is_resizable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IM_ASSERT(Buf == obj->TextA.Data);
|
IM_ASSERT(Buf == obj->TextA.Data);
|
||||||
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
|
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
|
||||||
obj->TextA.resize(new_buf_size + 1);
|
obj->TextA.resize(new_buf_size + 1);
|
||||||
|
|
@ -4327,11 +4336,12 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||||
memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
|
memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
|
||||||
Buf[BufTextLen + new_text_len] = '\0';
|
Buf[BufTextLen + new_text_len] = '\0';
|
||||||
|
|
||||||
if (CursorPos >= pos)
|
|
||||||
CursorPos += new_text_len;
|
|
||||||
SelectionStart = SelectionEnd = CursorPos;
|
|
||||||
BufDirty = true;
|
BufDirty = true;
|
||||||
BufTextLen += new_text_len;
|
BufTextLen += new_text_len;
|
||||||
|
if (CursorPos >= pos)
|
||||||
|
CursorPos += new_text_len;
|
||||||
|
CursorPos = ImClamp(CursorPos, 0, BufTextLen);
|
||||||
|
SelectionStart = SelectionEnd = CursorPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::PushPasswordFont()
|
void ImGui::PushPasswordFont()
|
||||||
|
|
@ -4824,7 +4834,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
{
|
{
|
||||||
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
|
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
|
||||||
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
|
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
|
||||||
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
|
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
|
||||||
for (ImGuiKey key : always_owned_keys)
|
for (ImGuiKey key : always_owned_keys)
|
||||||
SetKeyOwner(key, id);
|
SetKeyOwner(key, id);
|
||||||
if (user_clicked)
|
if (user_clicked)
|
||||||
|
|
@ -5032,7 +5042,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
|
|
||||||
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
|
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
|
||||||
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
||||||
const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true);
|
const bool is_enter = Shortcut(ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiKey_KeypadEnter, f_repeat, id);
|
||||||
|
const bool is_ctrl_enter = Shortcut(ImGuiMod_Ctrl | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_KeypadEnter, f_repeat, id);
|
||||||
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
|
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
|
||||||
const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id));
|
const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id));
|
||||||
|
|
||||||
|
|
@ -5067,11 +5078,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
}
|
}
|
||||||
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
|
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
|
||||||
}
|
}
|
||||||
else if (is_enter_pressed || is_gamepad_validate)
|
else if (is_enter || is_ctrl_enter || is_gamepad_validate)
|
||||||
{
|
{
|
||||||
// Determine if we turn Enter into a \n character
|
// Determine if we turn Enter into a \n character
|
||||||
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
||||||
if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != io.KeyCtrl))
|
if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != is_ctrl_enter))
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
||||||
|
|
@ -5081,7 +5092,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
}
|
}
|
||||||
else if (!is_readonly)
|
else if (!is_readonly)
|
||||||
{
|
{
|
||||||
unsigned int c = '\n'; // Insert new line
|
// Insert new line
|
||||||
|
unsigned int c = '\n';
|
||||||
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
||||||
state->OnCharPressed(c);
|
state->OnCharPressed(c);
|
||||||
}
|
}
|
||||||
|
|
@ -5264,10 +5276,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
callback_data.BufTextLen = state->TextLen;
|
callback_data.BufTextLen = state->TextLen;
|
||||||
callback_data.BufSize = state->BufCapacity;
|
callback_data.BufSize = state->BufCapacity;
|
||||||
callback_data.BufDirty = false;
|
callback_data.BufDirty = false;
|
||||||
|
callback_data.CursorPos = state->Stb->cursor;
|
||||||
const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
|
callback_data.SelectionStart = state->Stb->select_start;
|
||||||
const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start;
|
callback_data.SelectionEnd = state->Stb->select_end;
|
||||||
const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end;
|
|
||||||
|
|
||||||
// Call user code
|
// Call user code
|
||||||
callback(&callback_data);
|
callback(&callback_data);
|
||||||
|
|
@ -5277,11 +5288,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
|
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
|
||||||
IM_ASSERT(callback_data.BufSize == state->BufCapacity);
|
IM_ASSERT(callback_data.BufSize == state->BufCapacity);
|
||||||
IM_ASSERT(callback_data.Flags == flags);
|
IM_ASSERT(callback_data.Flags == flags);
|
||||||
const bool buf_dirty = callback_data.BufDirty;
|
if (callback_data.BufDirty || callback_data.CursorPos != state->Stb->cursor)
|
||||||
if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; }
|
state->CursorFollow = true;
|
||||||
if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; }
|
state->Stb->cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen);
|
||||||
if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; }
|
state->Stb->select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen);
|
||||||
if (buf_dirty)
|
state->Stb->select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen);
|
||||||
|
if (callback_data.BufDirty)
|
||||||
{
|
{
|
||||||
// Callback may update buffer and thus set buf_dirty even in read-only mode.
|
// Callback may update buffer and thus set buf_dirty even in read-only mode.
|
||||||
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
|
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
|
||||||
|
|
@ -5405,7 +5417,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
line_index->Offsets.resize(0);
|
line_index->Offsets.resize(0);
|
||||||
int line_count = 1;
|
int line_count = 1;
|
||||||
if (is_multiline)
|
if (is_multiline)
|
||||||
line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, (render_cursor && state && state->CursorFollow) ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end);
|
{
|
||||||
|
// If scrolling is expected to change build full index.
|
||||||
|
// FIXME-OPT: Could append to index when new value of line_visible_n1 becomes bigger, see second call to CalcClipRectVisibleItemsY() below.
|
||||||
|
bool will_scroll_y = state && ((state->CursorFollow && render_cursor) || (state->CursorCenterY && (render_cursor || render_selection)));
|
||||||
|
line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, will_scroll_y ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end);
|
||||||
|
}
|
||||||
line_index->EndOffset = (int)(buf_display_end - buf_display);
|
line_index->EndOffset = (int)(buf_display_end - buf_display);
|
||||||
line_visible_n1 = ImMin(line_visible_n1, line_count);
|
line_visible_n1 = ImMin(line_visible_n1, line_count);
|
||||||
|
|
||||||
|
|
@ -8210,8 +8227,8 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right-click handling.
|
// Right-click handling.
|
||||||
// FIXME-MULTISELECT: Currently filtered out by ImGuiMultiSelectFlags_NoAutoSelect but maybe should be moved to Selectable(). See https://github.com/ocornut/imgui/pull/5816
|
// FIXME-MULTISELECT: Maybe should be moved to Selectable()? Also see #5816, #8200, #9015
|
||||||
if (hovered && IsMouseClicked(1) && (flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
|
if (hovered && IsMouseClicked(1) && (flags & (ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoSelectOnRightClick)) == 0)
|
||||||
{
|
{
|
||||||
if (g.ActiveId != 0 && g.ActiveId != id)
|
if (g.ActiveId != 0 && g.ActiveId != id)
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
|
|
@ -10840,8 +10857,8 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||||
const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered);
|
const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered);
|
||||||
if (unsaved_marker_visible)
|
if (unsaved_marker_visible)
|
||||||
{
|
{
|
||||||
const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz));
|
ImVec2 bullet_pos = button_pos + ImVec2(button_sz, button_sz) * 0.5f;
|
||||||
RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));
|
RenderBullet(draw_list, bullet_pos, GetColorU32(ImGuiCol_UnsavedMarker));
|
||||||
}
|
}
|
||||||
else if (close_button_visible)
|
else if (close_button_visible)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@
|
||||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
||||||
// - Added name to struct or it may be forward declared in our code.
|
// - Added name to struct or it may be forward declared in our code.
|
||||||
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
// - Changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
|
||||||
|
// Grep for [DEAR IMGUI] to find some changes.
|
||||||
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
||||||
|
|
||||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||||
|
|
@ -39,6 +40,7 @@
|
||||||
//
|
//
|
||||||
// VERSION HISTORY
|
// VERSION HISTORY
|
||||||
//
|
//
|
||||||
|
// !!!! (2025-10-23) changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
|
||||||
// 1.14 (2021-07-11) page up/down, various fixes
|
// 1.14 (2021-07-11) page up/down, various fixes
|
||||||
// 1.13 (2019-02-07) fix bug in undo size management
|
// 1.13 (2019-02-07) fix bug in undo size management
|
||||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||||
|
|
@ -147,7 +149,8 @@
|
||||||
// as manually wordwrapping for end-of-line positioning
|
// as manually wordwrapping for end-of-line positioning
|
||||||
//
|
//
|
||||||
// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
|
// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
|
||||||
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
|
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) try to insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
|
||||||
|
// returns number of characters actually inserted. [DEAR IMGUI]
|
||||||
//
|
//
|
||||||
// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
|
// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
|
||||||
//
|
//
|
||||||
|
|
@ -775,7 +778,8 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
stb_textedit_delete_selection(str,state);
|
stb_textedit_delete_selection(str,state);
|
||||||
// try to insert the characters
|
// try to insert the characters
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
|
len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len);
|
||||||
|
if (len) {
|
||||||
stb_text_makeundo_insert(state, state->cursor, len);
|
stb_text_makeundo_insert(state, state->cursor, len);
|
||||||
state->cursor += len;
|
state->cursor += len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
|
@ -800,13 +804,15 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta
|
||||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
|
||||||
|
if (text_len) {
|
||||||
state->cursor += text_len;
|
state->cursor += text_len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stb_textedit_delete_selection(str, state); // implicitly clamps
|
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
|
||||||
|
if (text_len) {
|
||||||
stb_text_makeundo_insert(state, state->cursor, text_len);
|
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||||
state->cursor += text_len;
|
state->cursor += text_len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
|
@ -1352,7 +1358,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// check type of recorded action:
|
// check type of recorded action:
|
||||||
if (u.insert_length) {
|
if (u.insert_length) {
|
||||||
// easy case: was a deletion, so we need to insert n characters
|
// easy case: was a deletion, so we need to insert n characters
|
||||||
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
|
u.insert_length = STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
|
||||||
s->undo_char_point -= u.insert_length;
|
s->undo_char_point -= u.insert_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1403,7 +1409,7 @@ static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
|
|
||||||
if (r.insert_length) {
|
if (r.insert_length) {
|
||||||
// easy case: need to insert n characters
|
// easy case: need to insert n characters
|
||||||
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
r.insert_length = STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
||||||
s->redo_char_point += r.insert_length;
|
s->redo_char_point += r.insert_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Build font atlases using FreeType instead of stb_truetype (which is the default
|
||||||
|
|
||||||
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`).
|
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`).
|
||||||
2. Add imgui_freetype.h/cpp alongside your project files.
|
2. Add imgui_freetype.h/cpp alongside your project files.
|
||||||
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file
|
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to make Dear ImGui automatically use the imgui_freetype loader. If your copy Dear ImGui is precompiled, you can always enable imgui_freetype by calling ImFontAtlas::SetFontLoader().
|
||||||
|
|
||||||
### About Gamma Correct Blending
|
### About Gamma Correct Blending
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue