update dear imgui from 1.92.6-docking to 1.92.7-docking
This commit is contained in:
parent
b549728a24
commit
85d1832a0c
@ -19,6 +19,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-19: Fixed issue in ImGui_ImplDX9_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||||
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||||
@ -448,6 +449,7 @@ void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
|
|||||||
}
|
}
|
||||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
{
|
{
|
||||||
|
if (tex->TexID != ImTextureID_Invalid)
|
||||||
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
|
if (LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID)
|
||||||
{
|
{
|
||||||
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-25: Mouse cursor is properly restored if changed by user app/code while using glfwSetInputMode(..., GLFW_CURSOR_DISABLED) or ImGuiConfigFlags_NoMouseCursorChange. Amend change from 2025-12-10.
|
||||||
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
|
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
|
||||||
// 2026-01-25: [Docking] Improve workarounds for cases where GLFW is unable to provide any reliable monitor info. Preserve existing monitor list when none of the new one is valid. (#9195, #7902, #5683)
|
// 2026-01-25: [Docking] Improve workarounds for cases where GLFW is unable to provide any reliable monitor info. Preserve existing monitor list when none of the new one is valid. (#9195, #7902, #5683)
|
||||||
// 2026-01-18: [Docking] Dynamically load X11 functions to avoid -lx11 linking requirement introduced on 2025-09-10.
|
// 2026-01-18: [Docking] Dynamically load X11 functions to avoid -lx11 linking requirement introduced on 2025-09-10.
|
||||||
@ -993,7 +994,10 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
|||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
bd->LastMouseCursor = nullptr; // Invalidate so that if user changes underlying cursor we will update it next time we can.
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-19: Fixed issue in ImGui_ImplMetal_RenderDrawData() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture().
|
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplMetal_CreateFontsTexture() and ImGui_ImplMetal_DestroyFontsTexture().
|
||||||
// 2025-02-03: Metal: Crash fix. (#8367)
|
// 2025-02-03: Metal: Crash fix. (#8367)
|
||||||
@ -319,7 +320,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
|||||||
[commandEncoder setScissorRect:scissorRect];
|
[commandEncoder setScissorRect:scissorRect];
|
||||||
|
|
||||||
// Bind texture, Draw
|
// Bind texture, Draw
|
||||||
if (ImTextureID tex_id = pcmd->GetTexID())
|
ImTextureID tex_id = pcmd->GetTexID();
|
||||||
|
if (tex_id != ImTextureID_Invalid)
|
||||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(void*)(intptr_t)(tex_id) atIndex:0];
|
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(void*)(intptr_t)(tex_id) atIndex:0];
|
||||||
|
|
||||||
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802)
|
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures. (#8802)
|
||||||
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
|
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
|
||||||
@ -284,7 +285,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
|||||||
{
|
{
|
||||||
// Create and upload new texture to graphics system
|
// Create and upload new texture to graphics system
|
||||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
const void* pixels = tex->GetPixels();
|
const void* pixels = tex->GetPixels();
|
||||||
GLuint gl_texture_id = 0;
|
GLuint gl_texture_id = 0;
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792)
|
// 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792)
|
||||||
@ -754,7 +755,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
|||||||
{
|
{
|
||||||
// Create and upload new texture to graphics system
|
// Create and upload new texture to graphics system
|
||||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
const void* pixels = tex->GetPixels();
|
const void* pixels = tex->GetPixels();
|
||||||
GLuint gl_texture_id = 0;
|
GLuint gl_texture_id = 0;
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-09: [Docking] Fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor+merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing foreign windows to be ignored when deciding of hovered viewport. (#9284)
|
||||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||||
// 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_MOUSEMOTION 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_MOUSEMOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786)
|
||||||
@ -564,14 +565,6 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
bd->WindowID = SDL_GetWindowID(window);
|
bd->WindowID = SDL_GetWindowID(window);
|
||||||
bd->Renderer = renderer;
|
bd->Renderer = renderer;
|
||||||
|
|
||||||
// SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960)
|
|
||||||
// We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame.
|
|
||||||
#ifndef __APPLE__
|
|
||||||
bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState;
|
|
||||||
#else
|
|
||||||
bd->MouseCanReportHoveredViewport = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||||
bd->MouseCanUseGlobalState = false;
|
bd->MouseCanUseGlobalState = false;
|
||||||
@ -589,6 +582,14 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
if (bd->MouseCanUseGlobalState)
|
if (bd->MouseCanUseGlobalState)
|
||||||
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
||||||
|
|
||||||
|
// SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960)
|
||||||
|
// We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame.
|
||||||
|
#ifndef __APPLE__
|
||||||
|
bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState;
|
||||||
|
#else
|
||||||
|
bd->MouseCanReportHoveredViewport = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
|
||||||
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-25: [Docking] Use SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED (SDL 3.4.0+) when available to avoid refreshing monitor work area every frame on Windows. (#8415)
|
||||||
|
// 2026-03-09: [Docking] Fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor+merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing foreign windows to be ignored when deciding of hovered viewport. (#9284)
|
||||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||||
// 2025-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
|
// 2025-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054)
|
||||||
@ -104,6 +106,7 @@
|
|||||||
#else
|
#else
|
||||||
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
|
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
|
||||||
#endif
|
#endif
|
||||||
|
#define SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED SDL_VERSION_ATLEAST(3,4,0)
|
||||||
|
|
||||||
// FIXME-LEGACY: remove when SDL 3.1.3 preview is released.
|
// FIXME-LEGACY: remove when SDL 3.1.3 preview is released.
|
||||||
#ifndef SDLK_APOSTROPHE
|
#ifndef SDLK_APOSTROPHE
|
||||||
@ -474,6 +477,9 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
|
|||||||
case SDL_EVENT_DISPLAY_REMOVED:
|
case SDL_EVENT_DISPLAY_REMOVED:
|
||||||
case SDL_EVENT_DISPLAY_MOVED:
|
case SDL_EVENT_DISPLAY_MOVED:
|
||||||
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
|
case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
|
||||||
|
#if SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED
|
||||||
|
case SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED:
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
bd->WantUpdateMonitors = true;
|
bd->WantUpdateMonitors = true;
|
||||||
return true;
|
return true;
|
||||||
@ -570,14 +576,6 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
bd->WindowID = SDL_GetWindowID(window);
|
bd->WindowID = SDL_GetWindowID(window);
|
||||||
bd->Renderer = renderer;
|
bd->Renderer = renderer;
|
||||||
|
|
||||||
// SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960)
|
|
||||||
// We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame.
|
|
||||||
#ifndef __APPLE__
|
|
||||||
bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState;
|
|
||||||
#else
|
|
||||||
bd->MouseCanReportHoveredViewport = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||||
bd->MouseCanUseGlobalState = false;
|
bd->MouseCanUseGlobalState = false;
|
||||||
@ -598,6 +596,14 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
io.BackendFlags |= ImGuiBackendFlags_HasParentViewport; // We can honor viewport->ParentViewportId by applying the corresponding parent/child relationship at platform level (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasParentViewport; // We can honor viewport->ParentViewportId by applying the corresponding parent/child relationship at platform level (optional)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960)
|
||||||
|
// We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame.
|
||||||
|
#ifndef __APPLE__
|
||||||
|
bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState;
|
||||||
|
#else
|
||||||
|
bd->MouseCanReportHoveredViewport = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
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;
|
||||||
@ -996,7 +1002,7 @@ void ImGui_ImplSDL3_NewFrame()
|
|||||||
ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
|
ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
|
||||||
|
|
||||||
// Update monitors
|
// Update monitors
|
||||||
#ifdef WIN32
|
#if defined(WIN32) && !SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED
|
||||||
bd->WantUpdateMonitors = true; // Keep polling under Windows to handle changes of work area when resizing task-bar (#8415)
|
bd->WantUpdateMonitors = true; // Keep polling under Windows to handle changes of work area when resizing task-bar (#8415)
|
||||||
#endif
|
#endif
|
||||||
if (bd->WantUpdateMonitors)
|
if (bd->WantUpdateMonitors)
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||||
|
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
|
||||||
// 2025-11-26: macOS version can use MSL shaders in order to support macOS 10.14+ (vs Metallib shaders requiring macOS 14+). Requires calling SDL_CreateGPUDevice() with SDL_GPU_SHADERFORMAT_MSL.
|
// 2025-11-26: macOS version can use MSL shaders in order to support macOS 10.14+ (vs Metallib shaders requiring macOS 14+). Requires calling SDL_CreateGPUDevice() with SDL_GPU_SHADERFORMAT_MSL.
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created.
|
// 2025-08-20: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and ImGui_ImplSDLGPU3_InitInfo::PresentMode to configure how secondary viewports are created.
|
||||||
@ -133,8 +135,7 @@ static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer*
|
|||||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||||
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo;
|
||||||
|
|
||||||
// FIXME-OPT: Not optimal, but this is fairly rarely called.
|
// There is no need for calling SDL_WaitForGPUIdle here, as SDL3 will handle deferred buffer deletion automatically.
|
||||||
SDL_WaitForGPUIdle(v->Device);
|
|
||||||
SDL_ReleaseGPUBuffer(v->Device, *buffer);
|
SDL_ReleaseGPUBuffer(v->Device, *buffer);
|
||||||
SDL_ReleaseGPUTransferBuffer(v->Device, *transferbuffer);
|
SDL_ReleaseGPUTransferBuffer(v->Device, *transferbuffer);
|
||||||
|
|
||||||
@ -312,6 +313,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
|
|||||||
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
|
static void ImGui_ImplSDLGPU3_DestroyTexture(ImTextureData* tex)
|
||||||
{
|
{
|
||||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||||
|
if (tex->GetTexID() != ImTextureID_Invalid)
|
||||||
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
|
if (SDL_GPUTexture* raw_tex = (SDL_GPUTexture*)(intptr_t)tex->GetTexID())
|
||||||
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
|
SDL_ReleaseGPUTexture(bd->InitInfo.Device, raw_tex);
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
// - Introduction, links and more at the top of imgui.cpp
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
|
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer2_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture().
|
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer2_CreateFontsTexture() and ImGui_ImplSDLRenderer2_DestroyFontsTexture().
|
||||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||||
@ -269,6 +270,7 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
|
|||||||
}
|
}
|
||||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
{
|
{
|
||||||
|
if (tex->TexID != ImTextureID_Invalid)
|
||||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||||
SDL_DestroyTexture(sdl_texture);
|
SDL_DestroyTexture(sdl_texture);
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
// - Introduction, links and more at the top of imgui.cpp
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
|
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture().
|
// 2025-06-11: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplSDLRenderer3_CreateFontsTexture() and ImGui_ImplSDLRenderer3_DestroyFontsTexture().
|
||||||
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color.
|
||||||
@ -256,7 +257,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
|||||||
{
|
{
|
||||||
// Create and upload new texture to graphics system
|
// Create and upload new texture to graphics system
|
||||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
|
|
||||||
// Create texture
|
// Create texture
|
||||||
@ -285,6 +286,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
|||||||
}
|
}
|
||||||
else if (tex->Status == ImTextureStatus_WantDestroy)
|
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
{
|
{
|
||||||
|
if (tex->TexID != ImTextureID_Invalid)
|
||||||
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
if (SDL_Texture* sdl_texture = (SDL_Texture*)(intptr_t)tex->TexID)
|
||||||
SDL_DestroyTexture(sdl_texture);
|
SDL_DestroyTexture(sdl_texture);
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-11: Vulkan: Added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying extra dynamic states to add when creating the VkPipeline. (#9211)
|
||||||
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)
|
// 2025-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)
|
||||||
// 2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
|
// 2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)
|
||||||
// 2025-11-24: [Helpers] Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784)
|
// 2025-11-24: [Helpers] Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784)
|
||||||
@ -537,14 +538,12 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
|||||||
// Setup scale and translation:
|
// Setup scale and translation:
|
||||||
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||||
{
|
{
|
||||||
float scale[2];
|
float constants[4];
|
||||||
scale[0] = 2.0f / draw_data->DisplaySize.x;
|
constants[0] = 2.0f / draw_data->DisplaySize.x; // Scale
|
||||||
scale[1] = 2.0f / draw_data->DisplaySize.y;
|
constants[1] = 2.0f / draw_data->DisplaySize.y;
|
||||||
float translate[2];
|
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
|
||||||
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
|
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
|
||||||
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
|
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants);
|
||||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
|
|
||||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,11 +1039,13 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc
|
|||||||
blend_info.attachmentCount = 1;
|
blend_info.attachmentCount = 1;
|
||||||
blend_info.pAttachments = color_attachment;
|
blend_info.pAttachments = color_attachment;
|
||||||
|
|
||||||
VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
ImVector<VkDynamicState> dynamic_states = info->ExtraDynamicStates;
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
||||||
|
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
||||||
VkPipelineDynamicStateCreateInfo dynamic_state = {};
|
VkPipelineDynamicStateCreateInfo dynamic_state = {};
|
||||||
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
dynamic_state.dynamicStateCount = (uint32_t)IM_COUNTOF(dynamic_states);
|
dynamic_state.dynamicStateCount = dynamic_states.Size;
|
||||||
dynamic_state.pDynamicStates = dynamic_states;
|
dynamic_state.pDynamicStates = dynamic_states.Data;
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo create_info = {};
|
VkGraphicsPipelineCreateInfo create_info = {};
|
||||||
create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
@ -1424,6 +1425,7 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the Descriptor Set:
|
// Update the Descriptor Set:
|
||||||
|
if (descriptor_set != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
VkDescriptorImageInfo desc_image[1] = {};
|
VkDescriptorImageInfo desc_image[1] = {};
|
||||||
desc_image[0].sampler = sampler;
|
desc_image[0].sampler = sampler;
|
||||||
@ -1838,7 +1840,6 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
|
|||||||
VkCommandPoolCreateInfo pool_info = {};
|
VkCommandPoolCreateInfo pool_info = {};
|
||||||
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
pool_info.queueFamilyIndex = queue_family;
|
pool_info.queueFamilyIndex = queue_family;
|
||||||
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
|
||||||
VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);
|
VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
|
|
||||||
@ -2011,7 +2012,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
|
|||||||
requestSurfaceImageFormats.push_back(format);
|
requestSurfaceImageFormats.push_back(format);
|
||||||
|
|
||||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, (size_t)requestSurfaceImageFormats.Size, requestSurfaceColorSpace);
|
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, requestSurfaceImageFormats.Size, requestSurfaceColorSpace);
|
||||||
|
|
||||||
// Select Present Mode
|
// Select Present Mode
|
||||||
// FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)
|
// FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)
|
||||||
|
|||||||
@ -90,6 +90,7 @@ struct ImGui_ImplVulkan_PipelineInfo
|
|||||||
// For Main and Secondary viewports
|
// For Main and Secondary viewports
|
||||||
uint32_t Subpass; //
|
uint32_t Subpass; //
|
||||||
VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
|
VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT
|
||||||
|
ImVector<VkDynamicState> ExtraDynamicStates; // Optional, allows to insert more dynamic states into our VkPipeline
|
||||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||||
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR
|
VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
|
||||||
|
// 2026-03-09: Removed support for Emscripten < 4.0.10. (#9281)
|
||||||
// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
|
// 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)
|
||||||
@ -57,17 +59,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.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.
|
// 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)
|
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
|
#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK must be defined!
|
||||||
#endif
|
#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)
|
#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN
|
#error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||||
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
|
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
|
||||||
// Using type alias until WGPU adopts the same naming convention (#8369)
|
// Using type alias until WGPU adopts the same naming convention (#8369)
|
||||||
using WGPUProgrammableStageDescriptor = WGPUComputeState;
|
using WGPUProgrammableStageDescriptor = WGPUComputeState;
|
||||||
@ -189,6 +188,60 @@ fn main(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
// Same shader as __shader_vert_wgsl[] but compiled as SPIRV.
|
||||||
|
// 'wgslc -o vert.spv vert.wgsl' + 'binary_to_compressed_c -u8 -nocompress vert.spv'
|
||||||
|
static const unsigned char __shader_vert_spirv[1996] =
|
||||||
|
{
|
||||||
|
3,2,35,7,0,3,1,0,1,0,23,0,90,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,12,0,0,0,0,0,78,0,0,0,109,97,105,110,0,0,0,0,8,0,0,0,12,0,0,0,13,0,0,0,16,0,0,0,18,0,0,0,19,
|
||||||
|
0,0,0,21,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,
|
||||||
|
0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,12,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,13,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,16,0,0,0,11,0,0,0,0,0,0,0,71,0,4,0,18,
|
||||||
|
0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,21,0,0,0,11,0,0,0,1,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,
|
||||||
|
0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,22,0,3,0,11,0,0,0,32,0,0,0,23,0,4,0,10,0,0,0,
|
||||||
|
11,0,0,0,2,0,0,0,32,0,4,0,9,0,0,0,1,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,1,0,0,0,59,0,4,0,9,0,0,0,12,0,0,0,1,0,0,0,23,0,4,0,15,0,0,0,11,0,0,0,4,0,0,0,32,0,4,0,14,0,0,0,1,0,0,0,15,
|
||||||
|
0,0,0,59,0,4,0,14,0,0,0,13,0,0,0,1,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,15,0,0,0,59,0,4,0,17,0,0,0,16,0,0,0,3,0,0,0,59,0,4,0,17,0,0,0,18,0,0,0,3,0,0,0,32,0,4,0,20,0,0,0,3,0,0,0,10,0,0,0,
|
||||||
|
59,0,4,0,20,0,0,0,19,0,0,0,3,0,0,0,32,0,4,0,22,0,0,0,3,0,0,0,11,0,0,0,59,0,4,0,22,0,0,0,21,0,0,0,3,0,0,0,30,0,5,0,24,0,0,0,15,0,0,0,15,0,0,0,10,0,0,0,30,0,5,0,25,0,0,0,10,0,0,0,10,
|
||||||
|
0,0,0,15,0,0,0,33,0,4,0,27,0,0,0,24,0,0,0,25,0,0,0,32,0,4,0,30,0,0,0,7,0,0,0,24,0,0,0,46,0,3,0,24,0,0,0,31,0,0,0,32,0,4,0,33,0,0,0,7,0,0,0,15,0,0,0,43,0,4,0,6,0,0,0,34,0,0,0,0,0,0,
|
||||||
|
0,24,0,4,0,36,0,0,0,15,0,0,0,4,0,0,0,43,0,4,0,11,0,0,0,40,0,0,0,0,0,0,0,43,0,4,0,11,0,0,0,41,0,0,0,0,0,128,63,43,0,4,0,6,0,0,0,44,0,0,0,1,0,0,0,32,0,4,0,47,0,0,0,7,0,0,0,10,0,0,0,43,
|
||||||
|
0,4,0,6,0,0,0,48,0,0,0,2,0,0,0,33,0,4,0,52,0,0,0,36,0,0,0,6,0,0,0,43,0,4,0,6,0,0,0,55,0,0,0,16,0,0,0,32,0,4,0,57,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,66,0,0,0,32,0,0,0,43,0,4,0,6,
|
||||||
|
0,0,0,72,0,0,0,48,0,0,0,19,0,2,0,79,0,0,0,33,0,3,0,80,0,0,0,79,0,0,0,54,0,5,0,24,0,0,0,23,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,59,0,5,0,30,0,0,0,29,
|
||||||
|
0,0,0,7,0,0,0,31,0,0,0,65,0,5,0,33,0,0,0,32,0,0,0,29,0,0,0,34,0,0,0,57,0,5,0,36,0,0,0,35,0,0,0,37,0,0,0,34,0,0,0,81,0,5,0,10,0,0,0,38,0,0,0,26,0,0,0,0,0,0,0,80,0,6,0,15,0,0,0,39,0,
|
||||||
|
0,0,38,0,0,0,40,0,0,0,41,0,0,0,145,0,5,0,15,0,0,0,42,0,0,0,35,0,0,0,39,0,0,0,62,0,4,0,32,0,0,0,42,0,0,0,0,0,0,0,65,0,5,0,33,0,0,0,43,0,0,0,29,0,0,0,44,0,0,0,81,0,5,0,15,0,0,0,45,0,
|
||||||
|
0,0,26,0,0,0,2,0,0,0,62,0,4,0,43,0,0,0,45,0,0,0,0,0,0,0,65,0,5,0,47,0,0,0,46,0,0,0,29,0,0,0,48,0,0,0,81,0,5,0,10,0,0,0,49,0,0,0,26,0,0,0,1,0,0,0,62,0,4,0,46,0,0,0,49,0,0,0,0,0,0,0,
|
||||||
|
61,0,5,0,24,0,0,0,50,0,0,0,29,0,0,0,0,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,54,0,5,0,36,0,0,0,37,0,0,0,0,0,0,0,52,0,0,0,55,0,3,0,6,0,0,0,51,0,0,0,248,0,2,0,53,0,0,0,134,0,5,0,6,0,0,0,54,
|
||||||
|
0,0,0,51,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,56,0,0,0,1,0,0,0,34,0,0,0,54,0,0,0,61,0,5,0,5,0,0,0,58,0,0,0,56,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,59,0,0,0,58,0,0,0,128,0,5,0,6,0,0,0,60,0,
|
||||||
|
0,0,55,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,61,0,0,0,60,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,62,0,0,0,1,0,0,0,34,0,0,0,61,0,0,0,61,0,5,0,5,0,0,0,63,0,0,0,62,0,0,0,0,0,0,0,124,0,4,0,15,0,0,
|
||||||
|
0,64,0,0,0,63,0,0,0,128,0,5,0,6,0,0,0,65,0,0,0,66,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,67,0,0,0,65,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,68,0,0,0,1,0,0,0,34,0,0,0,67,0,0,0,61,0,5,0,5,0,0,0,
|
||||||
|
69,0,0,0,68,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,70,0,0,0,69,0,0,0,128,0,5,0,6,0,0,0,71,0,0,0,72,0,0,0,51,0,0,0,134,0,5,0,6,0,0,0,73,0,0,0,71,0,0,0,55,0,0,0,65,0,6,0,57,0,0,0,74,0,0,0,
|
||||||
|
1,0,0,0,34,0,0,0,73,0,0,0,61,0,5,0,5,0,0,0,75,0,0,0,74,0,0,0,0,0,0,0,124,0,4,0,15,0,0,0,76,0,0,0,75,0,0,0,80,0,7,0,36,0,0,0,77,0,0,0,59,0,0,0,64,0,0,0,70,0,0,0,76,0,0,0,254,0,2,0,77,
|
||||||
|
0,0,0,56,0,1,0,54,0,5,0,79,0,0,0,78,0,0,0,0,0,0,0,80,0,0,0,248,0,2,0,81,0,0,0,61,0,5,0,10,0,0,0,82,0,0,0,8,0,0,0,0,0,0,0,61,0,5,0,10,0,0,0,83,0,0,0,12,0,0,0,0,0,0,0,61,0,5,0,15,0,0,
|
||||||
|
0,84,0,0,0,13,0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,85,0,0,0,82,0,0,0,83,0,0,0,84,0,0,0,57,0,5,0,24,0,0,0,86,0,0,0,23,0,0,0,85,0,0,0,81,0,5,0,15,0,0,0,87,0,0,0,86,0,0,0,0,0,0,0,62,0,4,0,
|
||||||
|
16,0,0,0,87,0,0,0,0,0,0,0,81,0,5,0,15,0,0,0,88,0,0,0,86,0,0,0,1,0,0,0,62,0,4,0,18,0,0,0,88,0,0,0,0,0,0,0,81,0,5,0,10,0,0,0,89,0,0,0,86,0,0,0,2,0,0,0,62,0,4,0,19,0,0,0,89,0,0,0,0,0,
|
||||||
|
0,0,62,0,4,0,21,0,0,0,41,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Same shader as __shader_frag_wgsl[] but compiled as SPIRV.
|
||||||
|
// 'wgslc -o frag.spv frag.wgsl' + 'binary_to_compressed_c -u8 -nocompress frag.spv'
|
||||||
|
static const unsigned char __shader_frag_spirv[1392] =
|
||||||
|
{
|
||||||
|
3,2,35,7,0,3,1,0,1,0,23,0,60,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,48,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,9,0,4,0,0,0,51,0,0,0,109,
|
||||||
|
97,105,110,0,0,0,0,15,0,0,0,18,0,0,0,19,0,0,0,22,0,0,0,16,0,3,0,51,0,0,0,7,0,0,0,71,0,4,0,4,0,0,0,6,0,0,0,16,0,0,0,72,0,5,0,3,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,71,0,3,0,3,0,0,0,2,0,0,
|
||||||
|
0,71,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,1,0,0,0,33,0,0,0,0,0,0,0,71,0,3,0,1,0,0,0,24,0,0,0,71,0,4,0,8,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,8,0,0,0,33,0,0,0,1,0,0,0,71,0,4,0,11,0,0,
|
||||||
|
0,34,0,0,0,1,0,0,0,71,0,4,0,11,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,15,0,0,0,11,0,0,0,15,0,0,0,71,0,4,0,18,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,22,0,0,0,30,
|
||||||
|
0,0,0,0,0,0,0,21,0,4,0,6,0,0,0,32,0,0,0,0,0,0,0,23,0,4,0,5,0,0,0,6,0,0,0,4,0,0,0,43,0,4,0,6,0,0,0,7,0,0,0,5,0,0,0,28,0,4,0,4,0,0,0,5,0,0,0,7,0,0,0,30,0,3,0,3,0,0,0,4,0,0,0,32,0,4,0,
|
||||||
|
2,0,0,0,2,0,0,0,3,0,0,0,59,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,26,0,2,0,10,0,0,0,32,0,4,0,9,0,0,0,0,0,0,0,10,0,0,0,59,0,4,0,9,0,0,0,8,0,0,0,0,0,0,0,22,0,3,0,14,0,0,0,32,0,0,0,25,0,9,0,13,
|
||||||
|
0,0,0,14,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,13,0,0,0,59,0,4,0,12,0,0,0,11,0,0,0,0,0,0,0,23,0,4,0,17,0,0,0,14,0,0,0,4,0,0,0,32,0,4,0,16,
|
||||||
|
0,0,0,1,0,0,0,17,0,0,0,59,0,4,0,16,0,0,0,15,0,0,0,1,0,0,0,59,0,4,0,16,0,0,0,18,0,0,0,1,0,0,0,23,0,4,0,21,0,0,0,14,0,0,0,2,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,21,0,0,0,59,0,4,0,20,0,0,0,
|
||||||
|
19,0,0,0,1,0,0,0,32,0,4,0,23,0,0,0,3,0,0,0,17,0,0,0,59,0,4,0,23,0,0,0,22,0,0,0,3,0,0,0,30,0,5,0,25,0,0,0,17,0,0,0,17,0,0,0,21,0,0,0,33,0,4,0,27,0,0,0,17,0,0,0,25,0,0,0,27,0,3,0,34,
|
||||||
|
0,0,0,13,0,0,0,23,0,4,0,38,0,0,0,14,0,0,0,3,0,0,0,32,0,4,0,40,0,0,0,2,0,0,0,5,0,0,0,43,0,4,0,6,0,0,0,41,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,42,0,0,0,4,0,0,0,19,0,2,0,52,0,0,0,33,0,3,0,53,
|
||||||
|
0,0,0,52,0,0,0,54,0,5,0,17,0,0,0,24,0,0,0,0,0,0,0,27,0,0,0,55,0,3,0,25,0,0,0,26,0,0,0,248,0,2,0,28,0,0,0,81,0,5,0,17,0,0,0,29,0,0,0,26,0,0,0,1,0,0,0,61,0,5,0,13,0,0,0,30,0,0,0,11,0,
|
||||||
|
0,0,0,0,0,0,61,0,5,0,10,0,0,0,31,0,0,0,8,0,0,0,0,0,0,0,81,0,5,0,21,0,0,0,32,0,0,0,26,0,0,0,2,0,0,0,86,0,5,0,34,0,0,0,33,0,0,0,30,0,0,0,31,0,0,0,87,0,6,0,17,0,0,0,35,0,0,0,33,0,0,0,
|
||||||
|
32,0,0,0,0,0,0,0,133,0,5,0,17,0,0,0,36,0,0,0,29,0,0,0,35,0,0,0,79,0,8,0,38,0,0,0,37,0,0,0,36,0,0,0,36,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,65,0,6,0,40,0,0,0,39,0,0,0,1,0,0,0,41,0,0,0,42,0,
|
||||||
|
0,0,61,0,5,0,5,0,0,0,43,0,0,0,39,0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,44,0,0,0,43,0,0,0,0,0,0,0,124,0,4,0,14,0,0,0,45,0,0,0,44,0,0,0,80,0,6,0,38,0,0,0,46,0,0,0,45,0,0,0,45,0,0,0,45,0,0,0,
|
||||||
|
12,0,7,0,38,0,0,0,47,0,0,0,48,0,0,0,26,0,0,0,37,0,0,0,46,0,0,0,81,0,5,0,14,0,0,0,49,0,0,0,36,0,0,0,3,0,0,0,80,0,5,0,17,0,0,0,50,0,0,0,47,0,0,0,49,0,0,0,254,0,2,0,50,0,0,0,56,0,1,0,
|
||||||
|
54,0,5,0,52,0,0,0,51,0,0,0,0,0,0,0,53,0,0,0,248,0,2,0,54,0,0,0,61,0,5,0,17,0,0,0,55,0,0,0,15,0,0,0,0,0,0,0,61,0,5,0,17,0,0,0,56,0,0,0,18,0,0,0,0,0,0,0,61,0,5,0,21,0,0,0,57,0,0,0,19,
|
||||||
|
0,0,0,0,0,0,0,80,0,6,0,25,0,0,0,58,0,0,0,55,0,0,0,56,0,0,0,57,0,0,0,57,0,5,0,17,0,0,0,59,0,0,0,24,0,0,0,58,0,0,0,62,0,4,0,22,0,0,0,59,0,0,0,0,0,0,0,253,0,1,0,56,0,1,0,
|
||||||
|
};
|
||||||
|
|
||||||
static void SafeRelease(ImDrawIdx*& res)
|
static void SafeRelease(ImDrawIdx*& res)
|
||||||
{
|
{
|
||||||
if (res)
|
if (res)
|
||||||
@ -259,19 +312,13 @@ static void SafeRelease(FrameResources& res)
|
|||||||
SafeRelease(res.VertexBufferHost);
|
SafeRelease(res.VertexBufferHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const char* wgsl_source)
|
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
|
||||||
{
|
{
|
||||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||||
|
|
||||||
#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 };
|
||||||
#else
|
|
||||||
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
|
|
||||||
wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
|
||||||
wgsl_desc.code = wgsl_source;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WGPUShaderModuleDescriptor desc = {};
|
WGPUShaderModuleDescriptor desc = {};
|
||||||
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
|
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
|
||||||
@ -279,11 +326,26 @@ 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_WGPU_EMSCRIPTEN)
|
|
||||||
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||||
#else
|
return stage_desc;
|
||||||
stage_desc.entryPoint = "main";
|
}
|
||||||
#endif
|
|
||||||
|
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
|
||||||
|
{
|
||||||
|
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||||
|
|
||||||
|
WGPUShaderSourceSPIRV spirv_desc = {};
|
||||||
|
spirv_desc.chain.sType = WGPUSType_ShaderSourceSPIRV;
|
||||||
|
spirv_desc.code = (const uint32_t *)spirv_binary;
|
||||||
|
spirv_desc.codeSize = ((uint32_t)(spirv_length / 4));
|
||||||
|
|
||||||
|
WGPUShaderModuleDescriptor desc = {};
|
||||||
|
desc.nextInChain = (WGPUChainedStruct*)&spirv_desc;
|
||||||
|
|
||||||
|
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||||
|
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
||||||
|
|
||||||
|
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||||
return stage_desc;
|
return stage_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,11 +464,7 @@ 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, },
|
{ "Dear ImGui Vertex buffer", WGPU_STRLEN, },
|
||||||
#else
|
|
||||||
"Dear ImGui Vertex buffer",
|
|
||||||
#endif
|
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
|
||||||
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
|
MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
|
||||||
false
|
false
|
||||||
@ -430,11 +488,7 @@ 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, },
|
{ "Dear ImGui Index buffer", WGPU_STRLEN, },
|
||||||
#else
|
|
||||||
"Dear ImGui Index buffer",
|
|
||||||
#endif
|
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
|
||||||
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
|
MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
|
||||||
false
|
false
|
||||||
@ -458,8 +512,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
|||||||
}
|
}
|
||||||
int64_t vb_write_size = MEMALIGN((char*)vtx_dst - (char*)fr->VertexBufferHost, 4);
|
int64_t vb_write_size = MEMALIGN((char*)vtx_dst - (char*)fr->VertexBufferHost, 4);
|
||||||
int64_t ib_write_size = MEMALIGN((char*)idx_dst - (char*)fr->IndexBufferHost, 4);
|
int64_t ib_write_size = MEMALIGN((char*)idx_dst - (char*)fr->IndexBufferHost, 4);
|
||||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
|
wgpuQueueWriteBuffer(bd->defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, (size_t)vb_write_size);
|
||||||
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
|
wgpuQueueWriteBuffer(bd->defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, (size_t)ib_write_size);
|
||||||
|
|
||||||
// Setup desired render state
|
// Setup desired render state
|
||||||
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
|
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
|
||||||
@ -566,11 +620,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex)
|
|||||||
|
|
||||||
// Create texture
|
// Create texture
|
||||||
WGPUTextureDescriptor tex_desc = {};
|
WGPUTextureDescriptor tex_desc = {};
|
||||||
#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
|
|
||||||
tex_desc.label = "Dear ImGui Texture";
|
|
||||||
#endif
|
|
||||||
tex_desc.dimension = WGPUTextureDimension_2D;
|
tex_desc.dimension = WGPUTextureDimension_2D;
|
||||||
tex_desc.size.width = tex->Width;
|
tex_desc.size.width = tex->Width;
|
||||||
tex_desc.size.height = tex->Height;
|
tex_desc.size.height = tex->Height;
|
||||||
@ -611,20 +661,12 @@ 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_WGPU_EMSCRIPTEN)
|
|
||||||
WGPUTexelCopyTextureInfo dst_view = {};
|
WGPUTexelCopyTextureInfo dst_view = {};
|
||||||
#else
|
|
||||||
WGPUImageCopyTexture dst_view = {};
|
|
||||||
#endif
|
|
||||||
dst_view.texture = backend_tex->Texture;
|
dst_view.texture = backend_tex->Texture;
|
||||||
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_WGPU_EMSCRIPTEN)
|
|
||||||
WGPUTexelCopyBufferLayout layout = {};
|
WGPUTexelCopyBufferLayout layout = {};
|
||||||
#else
|
|
||||||
WGPUTextureDataLayout layout = {};
|
|
||||||
#endif
|
|
||||||
layout.offset = 0;
|
layout.offset = 0;
|
||||||
layout.bytesPerRow = tex->Width * tex->BytesPerPixel;
|
layout.bytesPerRow = tex->Width * tex->BytesPerPixel;
|
||||||
layout.rowsPerImage = upload_h;
|
layout.rowsPerImage = upload_h;
|
||||||
@ -642,11 +684,7 @@ 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, },
|
{ "Dear ImGui Uniform buffer", WGPU_STRLEN, },
|
||||||
#else
|
|
||||||
"Dear ImGui Uniform buffer",
|
|
||||||
#endif
|
|
||||||
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
|
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
|
||||||
MEMALIGN(sizeof(Uniforms), 16),
|
MEMALIGN(sizeof(Uniforms), 16),
|
||||||
false
|
false
|
||||||
@ -703,14 +741,15 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||||||
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
|
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
|
||||||
|
|
||||||
// Create the vertex shader
|
// Create the vertex shader
|
||||||
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_vert_wgsl);
|
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
|
||||||
|
if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv));
|
||||||
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
|
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
|
||||||
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
|
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
|
||||||
|
|
||||||
// Vertex input configuration
|
// Vertex input configuration
|
||||||
WGPUVertexAttribute attribute_desc[] =
|
WGPUVertexAttribute attribute_desc[] =
|
||||||
{
|
{
|
||||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
|
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
|
||||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
|
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
|
||||||
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
|
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
|
||||||
@ -731,7 +770,8 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||||||
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
|
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
|
||||||
|
|
||||||
// Create the pixel shader
|
// Create the pixel shader
|
||||||
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__shader_frag_wgsl);
|
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
|
||||||
|
if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv));
|
||||||
|
|
||||||
// Create the blending setup
|
// Create the blending setup
|
||||||
WGPUBlendState blend_state = {};
|
WGPUBlendState blend_state = {};
|
||||||
@ -758,11 +798,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_WGPU_EMSCRIPTEN)
|
|
||||||
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
||||||
#else
|
|
||||||
depth_stencil_state.depthWriteEnabled = false;
|
|
||||||
#endif
|
|
||||||
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
|
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
|
||||||
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
|
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
|
||||||
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
|
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
|
||||||
@ -847,11 +883,9 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
|
|||||||
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
|
io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)";
|
||||||
#endif
|
#endif
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#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)";
|
io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)";
|
||||||
#endif
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
|
io.BackendRendererName = "imgui_impl_wgpu (WGVK, Native)";
|
||||||
#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.
|
||||||
@ -923,7 +957,7 @@ void ImGui_ImplWGPU_NewFrame()
|
|||||||
|
|
||||||
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
|
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
|
||||||
{
|
{
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
|
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
|
||||||
#else
|
#else
|
||||||
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
|
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
|
||||||
@ -940,7 +974,7 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helpers to obtain a string
|
// Helpers to obtain a string
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
|
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
|||||||
@ -3,14 +3,16 @@
|
|||||||
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess)
|
||||||
|
|
||||||
// When targeting native platforms:
|
// 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, IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_WGVK *must* be provided.
|
||||||
// When targeting Emscripten:
|
// 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 now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN and requires Emscripten 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'.
|
||||||
|
// - Emscripten < 4.0.10 is not supported anymore (old '-sUSE_WEBGPU=1' option).
|
||||||
// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten.
|
// - 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 may 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
|
||||||
|
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||||
|
|
||||||
// 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!
|
||||||
@ -35,20 +37,7 @@
|
|||||||
// Setup Emscripten default if not specified.
|
// Setup Emscripten default if not specified.
|
||||||
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
#include <emscripten/version.h>
|
#include <emscripten/version.h>
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN_MAJOR__
|
|
||||||
#if (__EMSCRIPTEN_MAJOR__ >= 4) && (__EMSCRIPTEN_MINOR__ >= 0) && (__EMSCRIPTEN_TINY__ >= 10)
|
|
||||||
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||||
#else
|
|
||||||
#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#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
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
@ -111,7 +100,7 @@ const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
|
|||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
|
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
|
||||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
|
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
|
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -23,21 +23,22 @@
|
|||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2026-03-31: [Viewports] Fixed setting/getting size when viewports have OS decorations (e.g. io.ConfigViewportsNoDecoration = false) and process is running in Per-Monitor V2 DPI mode. (#8897)
|
||||||
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
||||||
// 2026-01-26: [Docking] Fixed an issue from 1.90.5 where newly appearing windows that are not parented to the main viewport don't have task bar icon appear before the windows was explicited refocused. (#7354, #8669)
|
// 2026-01-26: [Viewports] Fixed an issue from 1.90.5 where newly appearing windows that are not parented to the main viewport don't have task bar icon appear before the windows was explicited refocused. (#7354, #8669)
|
||||||
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
||||||
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
||||||
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
|
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
|
||||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||||
// 2025-06-02: [Docking] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code.
|
// 2025-06-02: [Viewports] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code.
|
||||||
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
|
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
|
||||||
// 2025-03-26: [Docking] Viewports: fixed an issue when closing a window from the OS close button (with io.ConfigViewportsNoDecoration = false) while user code was discarding the 'bool* p_open = false' output from Begin(). Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was still submitting it.
|
// 2025-03-26: [Viewports] Viewports: fixed an issue when closing a window from the OS close button (with io.ConfigViewportsNoDecoration = false) while user code was discarding the 'bool* p_open = false' output from Begin(). Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was still submitting it.
|
||||||
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468)
|
||||||
// 2025-02-21: [Docking] WM_SETTINGCHANGE's SPI_SETWORKAREA message also triggers a refresh of monitor list. (#8415)
|
// 2025-02-21: [Viewports] WM_SETTINGCHANGE's SPI_SETWORKAREA message also triggers a refresh of monitor list. (#8415)
|
||||||
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support.
|
||||||
// 2024-11-21: [Docking] Fixed a crash when multiple processes are running with multi-viewports, caused by misusage of GetProp(). (#8162, #8069)
|
// 2024-11-21: [Viewports] Fixed a crash when multiple processes are running with multi-viewports, caused by misusage of GetProp(). (#8162, #8069)
|
||||||
// 2024-10-28: [Docking] Rely on property stored inside HWND to retrieve context/viewport, should facilitate attempt to use this for parallel contexts. (#8069)
|
// 2024-10-28: [Viewports] Rely on property stored inside HWND to retrieve context/viewport, should facilitate attempt to use this for parallel contexts. (#8069)
|
||||||
// 2024-09-16: [Docking] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971)
|
// 2024-09-16: [Viewports] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971)
|
||||||
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
||||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
||||||
// 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL).
|
// 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL).
|
||||||
@ -108,6 +109,7 @@
|
|||||||
typedef DWORD(WINAPI* PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
typedef DWORD(WINAPI* PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||||
typedef DWORD(WINAPI* PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
typedef DWORD(WINAPI* PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||||
#endif
|
#endif
|
||||||
|
typedef BOOL(WINAPI* PFN_AdjustWindowRectExForDpi)(LPRECT, DWORD, BOOL, DWORD, UINT);
|
||||||
|
|
||||||
// Clang/GCC warnings with -Weverything
|
// Clang/GCC warnings with -Weverything
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
@ -124,6 +126,7 @@ typedef DWORD(WINAPI* PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
|||||||
static void ImGui_ImplWin32_InitMultiViewportSupport(bool platform_has_own_dc);
|
static void ImGui_ImplWin32_InitMultiViewportSupport(bool platform_has_own_dc);
|
||||||
static void ImGui_ImplWin32_ShutdownMultiViewportSupport();
|
static void ImGui_ImplWin32_ShutdownMultiViewportSupport();
|
||||||
static void ImGui_ImplWin32_UpdateMonitors();
|
static void ImGui_ImplWin32_UpdateMonitors();
|
||||||
|
static bool ImGui_ImplWin32_IsDpiAwarenessPerMonitorAwareV2();
|
||||||
|
|
||||||
struct ImGui_ImplWin32_Data
|
struct ImGui_ImplWin32_Data
|
||||||
{
|
{
|
||||||
@ -136,6 +139,8 @@ struct ImGui_ImplWin32_Data
|
|||||||
ImGuiMouseCursor LastMouseCursor;
|
ImGuiMouseCursor LastMouseCursor;
|
||||||
UINT32 KeyboardCodePage;
|
UINT32 KeyboardCodePage;
|
||||||
bool WantUpdateMonitors;
|
bool WantUpdateMonitors;
|
||||||
|
bool IsPerMonitorDpiAwareV2;
|
||||||
|
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi;
|
||||||
|
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
bool HasGamepad;
|
bool HasGamepad;
|
||||||
@ -213,6 +218,10 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
|||||||
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext());
|
||||||
ImGui_ImplWin32_InitMultiViewportSupport(platform_has_own_dc);
|
ImGui_ImplWin32_InitMultiViewportSupport(platform_has_own_dc);
|
||||||
|
|
||||||
|
if (HINSTANCE user32_dll = ::GetModuleHandleA("user32.dll"))
|
||||||
|
bd->AdjustWindowRectExForDpi = (PFN_AdjustWindowRectExForDpi)::GetProcAddress(user32_dll, "AdjustWindowRectExForDpi");
|
||||||
|
bd->IsPerMonitorDpiAwareV2 = ImGui_ImplWin32_IsDpiAwarenessPerMonitorAwareV2();
|
||||||
|
|
||||||
// Dynamically load XInput library
|
// Dynamically load XInput library
|
||||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
bd->WantUpdateHasGamepad = true;
|
bd->WantUpdateHasGamepad = true;
|
||||||
@ -941,6 +950,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
|
|||||||
return 0;
|
return 0;
|
||||||
case WM_DPICHANGED:
|
case WM_DPICHANGED:
|
||||||
{
|
{
|
||||||
|
// FIXME-DPI: see SDL3's WM_GETDPISCALEDSIZE handler.
|
||||||
const RECT* suggested_rect = (RECT*)lParam;
|
const RECT* suggested_rect = (RECT*)lParam;
|
||||||
if (io.ConfigDpiScaleViewports)
|
if (io.ConfigDpiScaleViewports)
|
||||||
::SetWindowPos(hwnd, nullptr, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
|
::SetWindowPos(hwnd, nullptr, suggested_rect->left, suggested_rect->top, suggested_rect->right - suggested_rect->left, suggested_rect->bottom - suggested_rect->top, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
@ -1006,6 +1016,8 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
|||||||
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
||||||
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
||||||
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
||||||
|
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_GetThreadDpiAwarenessContext)(); // "
|
||||||
|
typedef BOOL(WINAPI* PFN_AreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT); // "
|
||||||
|
|
||||||
// Helper function to enable DPI awareness without setting up a manifest
|
// Helper function to enable DPI awareness without setting up a manifest
|
||||||
void ImGui_ImplWin32_EnableDpiAwareness()
|
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||||
@ -1037,6 +1049,18 @@ void ImGui_ImplWin32_EnableDpiAwareness()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplWin32_IsDpiAwarenessPerMonitorAwareV2()
|
||||||
|
{
|
||||||
|
if (!_IsWindows10OrGreater())
|
||||||
|
return false;
|
||||||
|
static HINSTANCE user32_dll = ::GetModuleHandleA("user32.dll");
|
||||||
|
PFN_GetThreadDpiAwarenessContext GetThreadDpiAwarenessContextFn = (PFN_GetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "GetThreadDpiAwarenessContext");
|
||||||
|
PFN_AreDpiAwarenessContextsEqual AreDpiAwarenessContextsEqualFn = (PFN_AreDpiAwarenessContextsEqual)::GetProcAddress(user32_dll, "AreDpiAwarenessContextsEqual");
|
||||||
|
if (GetThreadDpiAwarenessContextFn && AreDpiAwarenessContextsEqualFn)
|
||||||
|
return AreDpiAwarenessContextsEqualFn(GetThreadDpiAwarenessContextFn(), DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(NOGDI)
|
#if defined(_MSC_VER) && !defined(NOGDI)
|
||||||
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
|
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
|
||||||
#endif
|
#endif
|
||||||
@ -1155,6 +1179,18 @@ static HWND ImGui_ImplWin32_GetHwndFromViewport(ImGuiViewport* viewport)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_AdjustWindowRect(ImGuiViewport* viewport, RECT* rect, DWORD style, DWORD ex_style)
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
if (bd->AdjustWindowRectExForDpi && bd->IsPerMonitorDpiAwareV2)
|
||||||
|
{
|
||||||
|
UINT dpi = (UINT)(viewport->DpiScale * 96.0f + 0.5f);
|
||||||
|
if (dpi != 0 && bd->AdjustWindowRectExForDpi(rect, style, FALSE, ex_style, dpi))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
::AdjustWindowRectEx(rect, style, FALSE, ex_style);
|
||||||
|
}
|
||||||
|
|
||||||
static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
|
static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
|
||||||
{
|
{
|
||||||
ImGui_ImplWin32_ViewportData* vd = IM_NEW(ImGui_ImplWin32_ViewportData)();
|
ImGui_ImplWin32_ViewportData* vd = IM_NEW(ImGui_ImplWin32_ViewportData)();
|
||||||
@ -1166,7 +1202,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
|
|||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
|
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
|
||||||
::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle);
|
ImGui_ImplWin32_AdjustWindowRect(viewport, &rect, vd->DwStyle, vd->DwExStyle);
|
||||||
vd->Hwnd = ::CreateWindowExW(
|
vd->Hwnd = ::CreateWindowExW(
|
||||||
vd->DwExStyle, L"ImGui Platform", L"Untitled", vd->DwStyle, // Style, class name, window name
|
vd->DwExStyle, L"ImGui Platform", L"Untitled", vd->DwStyle, // Style, class name, window name
|
||||||
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area
|
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area
|
||||||
@ -1259,7 +1295,7 @@ static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport)
|
|||||||
::SetWindowLong(vd->Hwnd, GWL_STYLE, vd->DwStyle);
|
::SetWindowLong(vd->Hwnd, GWL_STYLE, vd->DwStyle);
|
||||||
::SetWindowLong(vd->Hwnd, GWL_EXSTYLE, vd->DwExStyle);
|
::SetWindowLong(vd->Hwnd, GWL_EXSTYLE, vd->DwExStyle);
|
||||||
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
|
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
|
||||||
::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle); // Client to Screen
|
ImGui_ImplWin32_AdjustWindowRect(viewport, &rect, vd->DwStyle, vd->DwExStyle); // Client to Screen
|
||||||
::SetWindowPos(vd->Hwnd, insert_after, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, swp_flag | SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
::SetWindowPos(vd->Hwnd, insert_after, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, swp_flag | SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
||||||
::ShowWindow(vd->Hwnd, SW_SHOWNA); // This is necessary when we alter the style
|
::ShowWindow(vd->Hwnd, SW_SHOWNA); // This is necessary when we alter the style
|
||||||
viewport->PlatformRequestMove = viewport->PlatformRequestResize = true;
|
viewport->PlatformRequestMove = viewport->PlatformRequestResize = true;
|
||||||
@ -1289,7 +1325,7 @@ static void ImGui_ImplWin32_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos)
|
|||||||
RECT rect = { (LONG)pos.x, (LONG)pos.y, (LONG)pos.x, (LONG)pos.y };
|
RECT rect = { (LONG)pos.x, (LONG)pos.y, (LONG)pos.x, (LONG)pos.y };
|
||||||
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
|
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
|
||||||
ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using
|
ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using
|
||||||
::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle);
|
ImGui_ImplWin32_AdjustWindowRect(viewport, &rect, vd->DwStyle, vd->DwExStyle);
|
||||||
::SetWindowPos(vd->Hwnd, nullptr, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
::SetWindowPos(vd->Hwnd, nullptr, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,7 +1345,7 @@ static void ImGui_ImplWin32_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
|||||||
RECT rect = { 0, 0, (LONG)size.x, (LONG)size.y };
|
RECT rect = { 0, 0, (LONG)size.x, (LONG)size.y };
|
||||||
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
|
if (viewport->Flags & ImGuiViewportFlags_OwnedByApp)
|
||||||
ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using
|
ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using
|
||||||
::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle); // Client to Screen
|
ImGui_ImplWin32_AdjustWindowRect(viewport, &rect, vd->DwStyle, vd->DwExStyle); // Client to Screen
|
||||||
::SetWindowPos(vd->Hwnd, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
::SetWindowPos(vd->Hwnd, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,187 @@ HOW TO UPDATE?
|
|||||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||||
- Please report any issue!
|
- Please report any issue!
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
VERSION 1.92.7 (Released 2026-04-02)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.7
|
||||||
|
|
||||||
|
Breaking Changes:
|
||||||
|
|
||||||
|
- Separator: fixed a legacy quirk where `Separator()` was submitting a zero-height
|
||||||
|
item for layout purpose, even though it draws a 1-pixel separator.
|
||||||
|
The fix could affect code e.g. computing height from multiple widgets in order to
|
||||||
|
allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
|
||||||
|
The "Console" example had such a bug:
|
||||||
|
float footer_height = style.ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||||
|
Should be:
|
||||||
|
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||||
|
When such idiom was used and assuming zero-height Separator, it is likely that
|
||||||
|
in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
|
||||||
|
- Multi-Select: renamed `ImGuiMultiSelectFlags_SelectOnClick` to `ImGuiMultiSelectFlags_SelectOnAuto`.
|
||||||
|
Kept inline redirection enum (will obsolete).
|
||||||
|
- Combo(), ListBox(): commented out legacy signatures which were obsoleted in 1.90
|
||||||
|
(Nov 2023), when the getter callback type was changed from:
|
||||||
|
bool (*getter)(void* user_data, int idx, const char** out_text)
|
||||||
|
To:
|
||||||
|
const char* (*getter)(void* user_data, int idx)
|
||||||
|
|
||||||
|
Other Changes:
|
||||||
|
|
||||||
|
- TreeNode:
|
||||||
|
- Moved `TreeNodeGetOpen()` helper to public API. I was hesitant to make this public
|
||||||
|
because I intend to provide a more generic and feature-full version, but in the meanwhile
|
||||||
|
this will do. (#3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
|
||||||
|
- In 'Demo->Property Editor' demonstrate a way to perform tree clipping by fast-forwarding
|
||||||
|
through non-visible chunks. (#3823, #9251, #6990, #6042)
|
||||||
|
Using SetNextItemStorageID() + TreeNodeGetOpen() makes this notably easier than
|
||||||
|
it was prior to 1.91.
|
||||||
|
- InputText:
|
||||||
|
- Shift+Enter in multi-line editor always adds a new line, regardless of
|
||||||
|
`ImGuiInputTextFlags_CtrlEnterForNewLine` being set or not. (#9239)
|
||||||
|
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing Enter will
|
||||||
|
deactivate/reactivate the item in order for e.g. `IsItemDeactivatedAfterEdit()`
|
||||||
|
signals to be emitted the same way regardless of that setting. (#9001, #9115)
|
||||||
|
- Fixed a glitch when using `ImGuiInputTextFlags_ElideLeft` where the local x offset
|
||||||
|
would be incorrect during the deactivation frame. (#9298)
|
||||||
|
- Fixed a crash introduced in 1.92.6 when handling `ImGuiInputTextFlags_CallbackResize`
|
||||||
|
in certain situations. (#9174)
|
||||||
|
- Fixed selection highlight Y1 offset being very slightly off (since 1.92.3). (#9311) [@v-ein]
|
||||||
|
- InputTextMultiline: fixed an issue introduced in 1.92.3 where line count calculated
|
||||||
|
for vertical scrollbar range would be +1 when the widget is inactive, word-wrap is
|
||||||
|
disabled and the text buffer ends with '\n'. Fixed a similar issue related to clipping
|
||||||
|
large amount of text.
|
||||||
|
- InputTextMultiline: avoid going through reactivation code and fixed losing revert value
|
||||||
|
when activating scrollbar.
|
||||||
|
- InputTextMultiline: fixed an issue where edit buffer wouldn't be reapplied to back
|
||||||
|
buffer on the `IsItemDeactivatedAfterEdit()` frame. This could create issues when
|
||||||
|
using the idiom of not applying edits before `IsItemDeactivatedAfterEdit()`.
|
||||||
|
(#9308, #8915, #8273)
|
||||||
|
- Tables:
|
||||||
|
- Allow reordering columns by dragging them in the context menu. (#9312)
|
||||||
|
- Context menu now presents columns in display order. (#9312)
|
||||||
|
- Fixed and clarified the behavior of using `TableSetupScrollFreeze()` with columns>1,
|
||||||
|
and where some of the columns within that range were Hidable.
|
||||||
|
- Before: `TableSetupScrollFreeze(N, 0)`: include the N left-most visible columns as
|
||||||
|
part of the scroll freeze. So if you intentionally hide columns <N, the scroll
|
||||||
|
freeze area would start covering the subsequent/following columns (N+1) etc.
|
||||||
|
- After: `TableSetupScrollFreeze(N, 0)`: include the N left-most columns (regardless of visibility),
|
||||||
|
part of the scroll freeze. So if you intentionally hide columns <N, the scroll as
|
||||||
|
freeze area will cover less columns.
|
||||||
|
- This is generally more sane and logical.
|
||||||
|
- Fixed dragging a header to reorder outside of visible bounds (due to horizontal scrolling)
|
||||||
|
from losing active id.
|
||||||
|
- Angled Headers: angled section for column being reordered via the regular headers
|
||||||
|
stays highlighted during reordering.
|
||||||
|
- Style:
|
||||||
|
- Fonts: fixed an issue introduced in 1.92.6 where `style.FontBaseSize` would be
|
||||||
|
cleared during the first frame if no fonts was explicitly added before.
|
||||||
|
- Border sizes are now scaled (and rounded) by `ScaleAllSizes()`.
|
||||||
|
- When using large values with `ScallAllSizes()`, the following items thickness
|
||||||
|
are scaled to integer amounts:
|
||||||
|
- `InputText()` caret/cursor thickness. (#7031)
|
||||||
|
- `CloseButton()` thickness.
|
||||||
|
- `TextLink()` underline thickness.
|
||||||
|
- `ColorButton()` border thickness.
|
||||||
|
- `Separator()` thickness, via scaling newly added `style.SeparatorSize`. (#2657, #9263)
|
||||||
|
- Nav:
|
||||||
|
- Popups: Shift+F10 or Menu key can now open popups menus when using
|
||||||
|
`BeginPopupContextItem()`, `BeginPopupContextWindow()` or `OpenPopupOnItemClick()`.
|
||||||
|
(#8803, #9270) [@exelix11, @ocornut]
|
||||||
|
- Changed Gamepad mapping for "Activate with Text Input" action: (#8803, #787)
|
||||||
|
- Previously: press North button (PS4/PS5 triangle, Switch X, Xbox Y).
|
||||||
|
- Now: long press (hold) Activate button (PS4/PS5 cross, Switch B, Xbox A) for ~0.60 secs.
|
||||||
|
This is rarely used, somehow easier to discover, and frees a button for other uses.
|
||||||
|
See updated Gamepad Control Sheets: https://www.dearimgui.com/controls_sheets
|
||||||
|
- Short Gamepad Activation press on InputText() always activate with Text Input mode.
|
||||||
|
- Popups: pressing North button (PS4/PS5 triangle, SwitchX, Xbox Y) also open popups menus.
|
||||||
|
- Multi-Select:
|
||||||
|
- Added `ImGuiMultiSelectFlags_SelectOnClickAlways` mode (rarely used).
|
||||||
|
This prevents Drag and Drop of multiple items, but it allows to start a new Box-Selection
|
||||||
|
from inside an existing selection (Excel style). (#9307, #1861)
|
||||||
|
- Clipper:
|
||||||
|
- Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false.
|
||||||
|
- Added `UserIndex` helper storage. This is solely a convenience for cases where
|
||||||
|
you may want to carry an index around.
|
||||||
|
- Always pulls current context on `ImGuiListClipper::Begin()`, consistent with public
|
||||||
|
API design, and avoids issues with clipper instances outliving contexts. (#9324, #5856)
|
||||||
|
- Scrollbar:
|
||||||
|
- Implemented a custom tweak to extend hit-testing bounding box when window is sitting
|
||||||
|
at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the
|
||||||
|
mouse at the extreme of the screen will reach the scrollbar. (#9276)
|
||||||
|
- Fixed an issue which could lead initial click to move the current scroll by a pixel.
|
||||||
|
- Button:
|
||||||
|
- Moved `ImGuiButtonFlags_AllowOverlap` from imgui_internal.h to imgui.h,
|
||||||
|
as a convenience for when using e.g. `InvisibleButton()`.
|
||||||
|
- Focus: fixed fallback "Debug" window temporarily taking focus and setting `io.WantCaptureKeyboard`
|
||||||
|
for one frame on e.g. application boot if no other windows are submitted. (#9243)
|
||||||
|
- DrawList:
|
||||||
|
- PathArcTo(): fixed erroneous segment count for pathologically small arcs on large
|
||||||
|
circles. (#9331, #9313) [@thedmd, @epajarre]
|
||||||
|
- Memory:
|
||||||
|
- Discard/GC of ImDrawList buffers for unused windows favor restoring them to
|
||||||
|
~Size*1.05 instead of Capacity when awakening again. Facilitate releasing ImDrawList
|
||||||
|
buffers after unusual usage spike. (#9303)
|
||||||
|
- Fixed `GetForegroundDrawList()`/`GetBackgroundDrawList()` per-viewport buffers not being
|
||||||
|
collected when unused for `io.ConfigMemoryCompactTimer` amount of time. (#9303)
|
||||||
|
- Demo: fixed `IMGUI_DEMO_MARKER` locations for examples applets. (#9261, #3689) [@pthom]
|
||||||
|
- Misc: added missing ImVec2/ImVec4 operators. (#9339, #8258) [@dkosmari, @ArashPartow]
|
||||||
|
- Internals:
|
||||||
|
- ButtonBehavior: fixed internal/low-level `ImGuiButtonFlags_PressedOnRelease`
|
||||||
|
(as well as equivalent `ImGuiSelectableFlags_SelectOnRelease` for Selectable) from
|
||||||
|
not taking current active id. `ImGuiButtonFlags_NoHoldingActiveID` allows that.
|
||||||
|
This was only used internally by MenuItem().
|
||||||
|
- Backends:
|
||||||
|
- DirectX9, OpenGL2, OpenGL3, Metal, SDLGPU3, SDLRenderer2, SDLRenderer3: fixed easy-to-fix
|
||||||
|
issues in code assuming ImTextureID_Invalid is always defined to 0. (#9295, #9310)
|
||||||
|
- GLFW: mouse cursor is properly restored if changed by user app/code while using
|
||||||
|
`glfwSetInputMode(..., GLFW_CURSOR_DISABLED)` or `ImGuiConfigFlags_NoMouseCursorChange`.
|
||||||
|
Amend optimization done in 1.92.6.
|
||||||
|
- SDLGPU3: removed unnecessary call to `SDL_WaitForGPUIdle()` when releasing
|
||||||
|
vertex/index buffers. (#9262) [@jaenis]
|
||||||
|
- WebGPU: fixed version check for Emscripten 5.0.0+.
|
||||||
|
- WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
|
||||||
|
- WebGPU: added support for WGVK native backend via `IMGUI_IMPL_WEBGPU_BACKEND_WGVK`,
|
||||||
|
using SPIRV shaders if WGSL is not available. (#9316, #9246, #9257) [@r-lyeh]
|
||||||
|
(WGVK is a lightweight alternative to Dawn or WGPU for native applications,
|
||||||
|
which is easier to build/setup, see: https://github.com/manuel5975p/WGVK)
|
||||||
|
- Examples:
|
||||||
|
- Emscripten: added `tabindex=-1` to canvas in our shell_minimal.htm. Without it,
|
||||||
|
the canvas was not focusable in the DOM, which in turn make some backends
|
||||||
|
(e.g. pongasoft/emscripten-glfw) not receive focus loss events. (#9259) [@pthom]
|
||||||
|
- Emscripten: fixed minor rendering issues with our HTML shell. (#9281) [@ypujante]
|
||||||
|
- hidden small blue outline when canvas is focused on Chrome.
|
||||||
|
- hidden scrollbar in Firefox.
|
||||||
|
- Vulkan: added `ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[]` to allow specifying
|
||||||
|
extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej]
|
||||||
|
- Vulkan: `ImGui_ImplVulkan_AddTexture()` skips updating descriptor_set if failing
|
||||||
|
to allocate one. (#8677) [@micb25]
|
||||||
|
- WebGPU: fixed undefined behaviors in example code for requesting adapter
|
||||||
|
and device. (#9246, #9256) [@r-lyeh]
|
||||||
|
- SDL2+WebGPU: fixed hi-dpi handling. (#9300) [@ypujante]
|
||||||
|
- GLFW/SDL2/SDL3+WebGPU: added support for WGVK. (#9316, #9246, #9257) [@r-lyeh, @ocornut]
|
||||||
|
- GLFW/SDL2/SDL3+WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
|
||||||
|
|
||||||
|
Docking+Viewports Branch:
|
||||||
|
|
||||||
|
- Viewports:
|
||||||
|
- Fixed an issue where the implicit "Debug" window would erroneously be targetted for
|
||||||
|
mouse inputs while hidden if (1) the implicit "Debug" window was used in a previous
|
||||||
|
session and moved to a secondary viewport and (2) the Platform Backend does not
|
||||||
|
support the ImGuiBackendFlags_HasMouseHoveredViewport feature. (#9254)
|
||||||
|
- Backends: SDL2, SDL3: fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor
|
||||||
|
and a merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing
|
||||||
|
foreign windows to be ignored when deciding of hovered viewport. (#9284) [@ravencgg]
|
||||||
|
- Backends: SDL3: use SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED (SDL 3.4.0+) when
|
||||||
|
available to avoid refreshing monitor work area every frame on Windows. (#8415)
|
||||||
|
- Backends: Win32: fixed setting/getting correct size when viewports have OS decorations
|
||||||
|
enabled (e.g. io.ConfigViewportsNoDecoration = false) and process is running in
|
||||||
|
Per-Monitor V2 DPI mode. (#8897) [@lailoken]
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
VERSION 1.92.6 (2026-02-17)
|
VERSION 1.92.6 (2026-02-17)
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@ -44,46 +225,46 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
|
|||||||
Breaking Changes:
|
Breaking Changes:
|
||||||
|
|
||||||
- Fonts:
|
- Fonts:
|
||||||
- AddFontDefault() now automatically selects an embedded font between:
|
- `AddFontDefault()` now automatically selects an embedded font between:
|
||||||
- AddFontDefaultBitmap(): classic pixel-clean font. Recommended at Size 13px with no scaling.
|
- `AddFontDefaultBitmap()`: classic pixel-clean font. Recommended at Size 13px with no scaling.
|
||||||
- AddFontDefaultVector(): new scalable font. Recommended at any higher size.
|
- `AddFontDefaultVector()`: new scalable font. Recommended at any higher size.
|
||||||
- The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi)
|
- The default selection is based on (style.FontSizeBase * FontScaleMain * FontScaleDpi)
|
||||||
reaching a small threshold, but old codebases may not set any of them properly.
|
reaching a small threshold, but old codebases may not set any of them properly.
|
||||||
As as a result, it is likely that old codebase may still default to AddFontDefaultBitmap().
|
As as a result, it is likely that old codebase may still default to AddFontDefaultBitmap().
|
||||||
- Prefer explicitly calling either of them based on your own logic!
|
- Prefer explicitly calling either of them based on your own logic!
|
||||||
You can call AddFontDefaultBitmap() to ensure legacy behavior.
|
You can call `AddFontDefaultBitmap()` to ensure legacy behavior.
|
||||||
- Fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did
|
- Fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did
|
||||||
erroneously make a copy of the font data, essentially defeating the purpose
|
erroneously make a copy of the font data, essentially defeating the purpose
|
||||||
of this flag and wasting memory (undetected since July 2015 and now spotted
|
of this flag and wasting memory (undetected since July 2015 and now spotted
|
||||||
by @TellowKrinkle, this is perhaps the oldest bug in Dear ImGui history,
|
by @TellowKrinkle, this is perhaps the oldest bug in Dear ImGui history,
|
||||||
albeit for a rarely used feature!) (#9086, #8465)
|
albeit for a rarely used feature!) (#9086, #8465)
|
||||||
HOWEVER, fixing this bug is likely to surface bugs in user/app code:
|
HOWEVER, fixing this bug is likely to surface bugs in user/app code:
|
||||||
- Prior to 1.92, font data only needs to be available during the atlas->AddFontXXX() call.
|
- Prior to 1.92, font data only needs to be available during the `atlas->AddFontXXX()` call.
|
||||||
Since 1.92, font data needs to available until atlas->RemoveFont(), or more typically
|
Since 1.92, font data needs to available until `atlas->RemoveFont()`, or more typically
|
||||||
until a shutdown of the owning context or font atlas.
|
until a shutdown of the owning context or font atlas.
|
||||||
- The fact that handling of `FontDataOwnedByAtlas = false` was broken bypassed
|
- The fact that handling of `FontDataOwnedByAtlas = false` was broken bypassed
|
||||||
the issue altogether.
|
the issue altogether.
|
||||||
- Removed ImFontConfig::PixelSnapV added in 1.92 which turns out is unnecessary
|
- Removed `ImFontConfig::PixelSnapV` added in 1.92 which turns out is unnecessary
|
||||||
(and misdocumented). Post-rescale GlyphOffset is always rounded.
|
(and was mis-documented). Post-rescale `GlyphOffset` is always rounded.
|
||||||
- Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for
|
- Popups: changed compile-time `ImGuiPopupFlags popup_flags = 1` default value to be `= 0` for
|
||||||
BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick().
|
`BeginPopupContextItem()`, `BeginPopupContextWindow()`, `BeginPopupContextVoid()`, `OpenPopupOnItemClick()`.
|
||||||
The default value has same meaning before and after. (#9157, #9146)
|
The default value has same meaning before and after. (#9157, #9146)
|
||||||
- Before this version, those functions had a 'ImGuiPopupFlags popup_flags = 1' default
|
- Before this version, those functions had a `ImGuiPopupFlags popup_flags = 1` default
|
||||||
value in their function signature. This was introduced by a change on 2020/06/23 (1.77)
|
value in their function signature. This was introduced by a change on 2020/06/23 (1.77)
|
||||||
while changing the signature from 'int mouse_button' to 'ImGuiPopupFlags popup_flags'
|
while changing the signature from `int mouse_button` to `ImGuiPopupFlags popup_flags`
|
||||||
and trying to preserve then-legacy behavior.
|
and trying to preserve then-legacy behavior.
|
||||||
- We have now changed this behavior to: cleanup a very old API quirk, facilitate use by
|
- We have now changed this behavior to: cleanup a very old API quirk, facilitate use by
|
||||||
bindings, and to remove the last and error-prone non-zero default value. Also because we
|
bindings, and to remove the last and error-prone non-zero default value. Also because we
|
||||||
deemed it extremely rare to use those helper functions with the Left mouse button!
|
deemed it extremely rare to use those helper functions with the Left mouse button!
|
||||||
As using the LMB would generally be triggered via another widget,
|
As using the LMB would generally be triggered via another widget,
|
||||||
e.g. a Button() + a OpenPopup()/BeginPopup() call.
|
e.g. a Button() + a OpenPopup()/BeginPopup() call.
|
||||||
- Before: The default = 1 means ImGuiPopupFlags_MouseButtonRight.
|
- Before: The default = 1 means `ImGuiPopupFlags_MouseButtonRight`.
|
||||||
Explicitly passing a literal 0 means ImGuiPopupFlags_MouseButtonLeft.
|
Explicitly passing a literal 0 means `ImGuiPopupFlags_MouseButtonLeft`.
|
||||||
- After: The default = 0 means ImGuiPopupFlags_MouseButtonRight.
|
- After: The default = 0 means `ImGuiPopupFlags_MouseButtonRight`.
|
||||||
Explicitly passing a literal 1 also means ImGuiPopupFlags_MouseButtonRight
|
Explicitly passing a literal 1 also means `ImGuiPopupFlags_MouseButtonRight`.
|
||||||
(if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
|
(if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
|
||||||
- TL;DR: if you don't want to use right mouse button for popups, always specify it
|
- TL;DR: if you don't want to use right mouse button for popups, always specify it
|
||||||
explicitly using a named ImGuiPopupFlags_MouseButtonXXXX value.
|
explicitly using a named `ImGuiPopupFlags_MouseButtonXXXX` value.
|
||||||
Recap:
|
Recap:
|
||||||
- BeginPopupContextItem("foo"); // Behavior unchanged (use Right button)
|
- BeginPopupContextItem("foo"); // Behavior unchanged (use Right button)
|
||||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft); // Behavior unchanged (use Left button)
|
- BeginPopupContextItem("foo", ImGuiPopupFlags_MouseButtonLeft); // Behavior unchanged (use Left button)
|
||||||
@ -93,11 +274,11 @@ Breaking Changes:
|
|||||||
- BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
|
- BeginPopupContextItem("foo", 0); // !! Behavior changed !! Was Left button. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft.
|
||||||
- BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
|
- BeginPopupContextItem("foo", ImGuiPopupFlags_NoReopen); // !! Behavior changed !! Was Left button + flags. Now will defaults to Right button! --> Use ImGuiPopupFlags_MouseButtonLeft | xxx.
|
||||||
- Commented out legacy names obsoleted in 1.90 (Sept 2023):
|
- Commented out legacy names obsoleted in 1.90 (Sept 2023):
|
||||||
- BeginChildFrame() --> BeginChild() with ImGuiChildFlags_FrameStyle flag.
|
- `BeginChildFrame()` --> `BeginChild()` with `ImGuiChildFlags_FrameStyle` flag.
|
||||||
- EndChildFrame() --> EndChild().
|
- `EndChildFrame()` --> `EndChild()`.
|
||||||
- ShowStackToolWindow() --> ShowIDStackToolWindow().
|
- `ShowStackToolWindow()` --> `ShowIDStackToolWindow()`.
|
||||||
- IM_OFFSETOF() --> offsetof().
|
- `IM_OFFSETOF()` --> `offsetof()`.
|
||||||
- IM_FLOOR() --> IM_TRUNC() [internal, for positive values only]
|
- `IM_FLOOR()` --> `IM_TRUNC()` [internal, for positive values only]
|
||||||
- Hashing: handling of "###" operator to reset to seed within a string identifier
|
- Hashing: handling of "###" operator to reset to seed within a string identifier
|
||||||
doesn't include the "###" characters in the output hash anymore:
|
doesn't include the "###" characters in the output hash anymore:
|
||||||
Before: `GetID("Hello###World") == GetID("###World") != GetID("World")`
|
Before: `GetID("Hello###World") == GetID("###World") != GetID("World")`
|
||||||
@ -106,11 +287,11 @@ Breaking Changes:
|
|||||||
identifiers using "###", and will allow fixing other dangling issues.
|
identifiers using "###", and will allow fixing other dangling issues.
|
||||||
- This will invalidate hashes (stored in .ini data) for Tables and Windows
|
- This will invalidate hashes (stored in .ini data) for Tables and Windows
|
||||||
that are using the "###" operators. (#713, #1698)
|
that are using the "###" operators. (#713, #1698)
|
||||||
- Renamed helper macro IM_ARRAYSIZE() -> IM_COUNTOF(). Kept redirection/legacy name.
|
- Renamed helper macro `IM_ARRAYSIZE()` -> `IM_COUNTOF()`. Kept redirection/legacy name.
|
||||||
- Backends:
|
- Backends:
|
||||||
- Vulkan: optional ImGui_ImplVulkanH_DestroyWindow() helper used by our example
|
- Vulkan: optional `ImGui_ImplVulkanH_DestroyWindow()` helper used by our example
|
||||||
code does not call vkDestroySurfaceKHR(): because surface is created by caller
|
code does not call `vkDestroySurfaceKHR()`: because surface is created by caller
|
||||||
of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent. (#9163)
|
of `ImGui_ImplVulkanH_CreateOrResizeWindow()`, it is more consistent. (#9163)
|
||||||
|
|
||||||
Other Changes:
|
Other Changes:
|
||||||
|
|
||||||
@ -128,22 +309,22 @@ Other Changes:
|
|||||||
- The font data was carefully subsetted, trimmed and compressed so the embedded
|
- The font data was carefully subsetted, trimmed and compressed so the embedded
|
||||||
data is ~14 KB. Embedding a scalable default font ensures that Dear ImGui can
|
data is ~14 KB. Embedding a scalable default font ensures that Dear ImGui can
|
||||||
be easily and readily used in all contexts, even without file system access.
|
be easily and readily used in all contexts, even without file system access.
|
||||||
|
- Expect minor fixes/improvements in following releases.
|
||||||
- As always you can opt-out of the embedded font data if desired.
|
- As always you can opt-out of the embedded font data if desired.
|
||||||
- `AddFontDefault()` now automatically selects an embedded font between
|
- `AddFontDefault()` now automatically selects an embedded font between
|
||||||
the classic pixel-looking one and the new scalable one.
|
the classic pixel-looking one and the new scalable one.
|
||||||
Prefer calling `AddFontDefaultVector()` or `AddFontDefaultBitmap()` explicitely.
|
Prefer calling `AddFontDefaultVector()` or `AddFontDefaultBitmap()` explicitly.
|
||||||
- Fixed a crash when trying to use `AddFont()` with `MergeMode==true` on a font that
|
- Fixed a crash when trying to use `AddFont()` with `MergeMode==true` on a font that
|
||||||
has already been rendered. (#9162) [@ocornut, @cyfewlp]
|
has already been rendered. (#9162) [@ocornut, @cyfewlp]
|
||||||
- Fixed an issue where using `PushFont()` from the implicit/fallback "Debug" window
|
- Fixed an issue where using `PushFont()` from the implicit/fallback "Debug" window
|
||||||
when its recorded state is collapsed would incorrectly early out. This would break
|
when its recorded state is collapsed would incorrectly early out. This would break
|
||||||
e.g. using direct draw-list calls such as GetForegroundDrawList() with current font.
|
e.g. using direct draw-list calls such as `GetForegroundDrawList()` with current font.
|
||||||
(#9210, #8865)
|
(#9210, #8865)
|
||||||
- Fixed an issue related to `EllipsisChar` handling, while changing
|
- Fixed an issue related to `EllipsisChar` handling, while changing
|
||||||
font loader or font loader flags dynamically in Style->Fonts menus.
|
font loader or font loader flags dynamically in Style->Fonts menus.
|
||||||
- imgui_freetype: fixed overwriting `ImFontConfig::PixelSnapH` when hinting
|
- imgui_freetype: fixed overwriting `ImFontConfig::PixelSnapH` when hinting
|
||||||
is enabled, creating side-effects when later disabling hinting or
|
is enabled, creating side-effects when later disabling hinting or
|
||||||
dynamically switching to stb_truetype rasterizer.
|
dynamically switching to stb_truetype rasterizer.
|
||||||
- Post rescale `ImFontConfig::GlyphOffset` is always rounded.
|
|
||||||
- Adding new fonts after removing all fonts mid-frame properly updates current state.
|
- Adding new fonts after removing all fonts mid-frame properly updates current state.
|
||||||
- Textures:
|
- Textures:
|
||||||
- Fixed a building issue when `ImTextureID` is defined as a struct.
|
- Fixed a building issue when `ImTextureID` is defined as a struct.
|
||||||
@ -154,7 +335,7 @@ Other Changes:
|
|||||||
- Made navigation into menu-bar auto wrap on X axis. (#9178)
|
- Made navigation into menu-bar auto wrap on X axis. (#9178)
|
||||||
- TreeNode:
|
- TreeNode:
|
||||||
- Fixed highlight position when used inside a line with a large text baseline offset.
|
- Fixed highlight position when used inside a line with a large text baseline offset.
|
||||||
(never quite worked in this situation; but then most of the time the text
|
(it never quite worked in this situation; but then most of the time the text
|
||||||
baseline offset ends up being zero or `FramePadding.y` for a given line).
|
baseline offset ends up being zero or `FramePadding.y` for a given line).
|
||||||
- Tables:
|
- Tables:
|
||||||
- Fixed an issue where a very thin scrolling table would advance parent layout
|
- Fixed an issue where a very thin scrolling table would advance parent layout
|
||||||
@ -180,7 +361,7 @@ Other Changes:
|
|||||||
- ImGuiInputTextCallbackData: Added `ID` and `EventActivated` members. (#9174)
|
- ImGuiInputTextCallbackData: Added `ID` and `EventActivated` members. (#9174)
|
||||||
- Text, InputText:
|
- Text, InputText:
|
||||||
- Reworked word-wrapping logic:
|
- Reworked word-wrapping logic:
|
||||||
- Try to not wrap in the middle of contiguous punctuations. (#8139, #8439, #9094)
|
- Try to not wrap in the middle of contiguous punctuation. (#8139, #8439, #9094)
|
||||||
- Try to not wrap between a punctuation and a digit. (#8503)
|
- Try to not wrap between a punctuation and a digit. (#8503)
|
||||||
- Inside `InputTextMultiline()` with WordWrap enabled: prefer keeping blanks at
|
- Inside `InputTextMultiline()` with WordWrap enabled: prefer keeping blanks at
|
||||||
the end of a line rather than at the beginning of next line. (#8990, #3237)
|
the end of a line rather than at the beginning of next line. (#8990, #3237)
|
||||||
@ -198,7 +379,7 @@ Other Changes:
|
|||||||
effectively making those actions faster on macOS/iOS retina screens.
|
effectively making those actions faster on macOS/iOS retina screens.
|
||||||
(changed this to use a style scale factor that's not fully formalized yet)
|
(changed this to use a style scale factor that's not fully formalized yet)
|
||||||
- Fixed an UBSan warning when using in a `ImGuiListClipper` region . (#9160)
|
- Fixed an UBSan warning when using in a `ImGuiListClipper` region . (#9160)
|
||||||
- Scrollbar: fixed a codepath leading to a divide-by-zero (which would not be
|
- Scrollbar: fixed a code-path leading to a divide-by-zero (which would not be
|
||||||
noticeable by user but detected by sanitizers). (#9089) [@judicaelclair]
|
noticeable by user but detected by sanitizers). (#9089) [@judicaelclair]
|
||||||
- InvisibleButton: allow calling with size (0,0) to fit to available content
|
- InvisibleButton: allow calling with size (0,0) to fit to available content
|
||||||
size. (#9166, #7623)
|
size. (#9166, #7623)
|
||||||
@ -219,7 +400,7 @@ Other Changes:
|
|||||||
- Shortcuts:
|
- Shortcuts:
|
||||||
- IsItemHovered() without `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
|
- IsItemHovered() without `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
|
||||||
doesn't filter out the signal when activated item is a shortcut remote activation;
|
doesn't filter out the signal when activated item is a shortcut remote activation;
|
||||||
(which mimicks what's done internally in the `ItemHoverable()` function). (#9138)
|
(which mimics what's done internally in the `ItemHoverable()` function). (#9138)
|
||||||
- Fixed tooltip placement being affected for a frame when located over an item
|
- Fixed tooltip placement being affected for a frame when located over an item
|
||||||
activated by `SetNextItemShortcut()`. (#9138)
|
activated by `SetNextItemShortcut()`. (#9138)
|
||||||
- Error Handling:
|
- Error Handling:
|
||||||
@ -257,7 +438,7 @@ Other Changes:
|
|||||||
- But you can also configure your system or debugger to automatically release
|
- But you can also configure your system or debugger to automatically release
|
||||||
mouse grab when crashing/breaking in debugger, e.g.
|
mouse grab when crashing/breaking in debugger, e.g.
|
||||||
- console: `setxkbmap -option grab:break_actions && xdotool key XF86Ungrab`
|
- console: `setxkbmap -option grab:break_actions && xdotool key XF86Ungrab`
|
||||||
- or use a GDB script to call SDL_CaptureMouse(false). See #3650.
|
- or use a GDB script to call `SDL_CaptureMouse(false)`. See #3650.
|
||||||
- On platforms other than X11 this is unnecessary.
|
- On platforms other than X11 this is unnecessary.
|
||||||
- SDL_GPU3: added `SamplerNearest` in `ImGui_ImplSDLGPU3_RenderState`.
|
- SDL_GPU3: added `SamplerNearest` in `ImGui_ImplSDLGPU3_RenderState`.
|
||||||
- SDL_GPU3: macOS version can use MSL shaders in order to support macOS 10.14+
|
- SDL_GPU3: macOS version can use MSL shaders in order to support macOS 10.14+
|
||||||
|
|||||||
@ -25,7 +25,7 @@ or view this file with any Markdown viewer.
|
|||||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||||
| **Q&A: Usage** |
|
| **Q&A: Usage** |
|
||||||
| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>Why is the wrong widget reacting when I click on one?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
|
| **[About the ID Stack system...](#q-about-the-id-stack-system)**<br>**[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**<br>**[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**<br>**[How can I animate the label of an existing widget?](#q-how-can-i-change-the-label-of-an-existing-widget) (using `###`)**<br>**[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)** |
|
||||||
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
|
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
|
||||||
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
|
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
|
||||||
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
|
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
|
||||||
@ -55,6 +55,7 @@ or view this file with any Markdown viewer.
|
|||||||
- Handy [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide to integrate Dear ImGui in an existing application.
|
- Handy [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide to integrate Dear ImGui in an existing application.
|
||||||
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
||||||
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||||
|
- See pthom's online [imgui_explorer](https://pthom.github.io/imgui_explorer) which is a web version of the demo with a source code browser.
|
||||||
- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||||
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
|
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
|
||||||
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
|
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
|
||||||
@ -262,15 +263,19 @@ ctx->RSSetScissorRects(1, &r);
|
|||||||
|
|
||||||
# Q&A: Usage
|
# Q&A: Usage
|
||||||
|
|
||||||
### Q: About the ID Stack system...
|
## Q: About the ID Stack system...
|
||||||
### Q: Why is my widget not reacting when I click on it?
|
|
||||||
### Q: Why is the wrong widget reacting when I click on one?
|
|
||||||
### Q: How can I have widgets with an empty label?
|
|
||||||
### Q: How can I have multiple widgets with the same label?
|
|
||||||
### Q: How can I have multiple windows with the same label?
|
|
||||||
|
|
||||||
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
|
**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
|
||||||
<br>**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
|
<br>**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
|
||||||
|
<br>Read the questions in this section for a more general understand of how labels and ID works in Dear ImGui.
|
||||||
|
|
||||||
|
TL;DR;
|
||||||
|
- Widgets labels are also used to compute Widgets unique identifiers.
|
||||||
|
- Unique identifiers are hashes of the label + of the parent scope (e.g. parent window or parent tree node labels).
|
||||||
|
- You can use `PushID()` to append to the identifier without making it visible.
|
||||||
|
- You can use `"##something"` in a label to append to the identifier without making it visible.
|
||||||
|
- You can use `"###something"` in a label to make the identifier ignore the visible part.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://github.com/user-attachments/assets/776a8315-1164-4178-9a8c-df52e0ff28aa"></td>
|
<td><img src="https://github.com/user-attachments/assets/776a8315-1164-4178-9a8c-df52e0ff28aa"></td>
|
||||||
@ -301,16 +306,99 @@ ImGui::End();
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
A primer on labels and the ID Stack...
|
### Q: How can I have multiple widgets with the same label?
|
||||||
|
|
||||||
|
A. When widgets are in a same scope and finite, you can use a `"##something"` suffix which will be part of the identifier but not visible as a label.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
|
||||||
|
Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
|
||||||
|
Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
|
||||||
|
```
|
||||||
|
|
||||||
|
B. More generally, e.g. in loops, you can use `PushID()/PopID()` to push a prefix which will be part of the identifier.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Using PushID() with a string
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
MyObject* obj = Objects[i];
|
||||||
|
PushID(obj->Name);
|
||||||
|
Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
|
||||||
|
PopID();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Using PushID() with an index
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
PushID(i);
|
||||||
|
Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
|
||||||
|
PopID();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: How can I have widgets with an empty label?
|
||||||
|
|
||||||
|
If you want to completely hide the label, but still need an ID:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
||||||
|
```
|
||||||
|
##### [Return to Index](#index)
|
||||||
|
|
||||||
|
### Q: How can I make a label dynamic?
|
||||||
|
|
||||||
|
Dear ImGui is very dynamic so you can submit different widgets every frame.
|
||||||
|
However, in order to preserve widget state (eg. which tree node is open; which button is focused) the library internaly refers to their unique ID.
|
||||||
|
|
||||||
|
Occasionally you might want to change a label while preserving a constant ID. This allows you to change/animate labels while persisting associated state.
|
||||||
|
For example, you may want to include varying information in a window title bar or button label.
|
||||||
|
|
||||||
|
Using "###" exclude the preceeding part from ID computation:
|
||||||
|
```cpp
|
||||||
|
Button("Hello###ID"); // Label = "Enable", ID = hash of (..., "ID")
|
||||||
|
Button("World###ID"); // Label = "Disable", ID = hash of (..., "ID") // Same ID, different label
|
||||||
|
```
|
||||||
|
Using a same ID ensure that associated related e.g. weither the widget is focused, won't be lost when the label changes.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://github.com/user-attachments/assets/2bf18756-e122-498d-bbd4-5c44bb1018d5"></td>
|
||||||
|
<td>
|
||||||
|
<pre lang="cpp">
|
||||||
|
// Window label has animating FPS counter
|
||||||
|
// Window ID stays the same = hash of "MyGame"
|
||||||
|
char buf[128];
|
||||||
|
sprintf(buf, "My game (%.1f FPS)###MyGame", io.Framerate);
|
||||||
|
ImGui::Begin(buf);
|
||||||
|
|
||||||
|
// Label changes between "Enable" and "Disable"
|
||||||
|
// ID stays the same = hash of ("MyGame", "MyButton")
|
||||||
|
if (ImGui::Button(enabled ? "Disable###MyButton" : "Enable###MyButton", { -FLT_MIN, 0.0f }))
|
||||||
|
enabled = !enabled;
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
</pre>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
(Hint: I'd suggest wrapping sprintf in something more compact to use, e.g. [ocornut/Str](https://github.com/ocornut/Str) for what I personally use).
|
||||||
|
|
||||||
|
##### [Return to Index](#index)
|
||||||
|
|
||||||
|
### General description of the label and ID Stack system
|
||||||
|
|
||||||
Dear ImGui internally needs to uniquely identify UI elements.
|
Dear ImGui internally needs to uniquely identify UI elements.
|
||||||
Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
|
Elements that are typically not clickable (such as calls to Text() functions) don't need an ID.
|
||||||
Interactive widgets (such as calls to Button buttons) need a unique ID.
|
Interactive widgets (such as calls to Button() functions) need a unique ID.
|
||||||
|
|
||||||
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
|
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
|
||||||
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
|
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
|
||||||
|
|
||||||
Since Dear ImGui 1.85, you can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
|
You can use `Demo>Tools>ID Stack Tool` or call `ImGui::ShowIDStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -364,20 +452,7 @@ Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo
|
|||||||
Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
|
Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
|
||||||
End();
|
End();
|
||||||
```
|
```
|
||||||
- If you want to completely hide the label, but still need an ID:
|
|
||||||
```cpp
|
|
||||||
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
|
|
||||||
```
|
|
||||||
- Occasionally/rarely you might want to change a label while preserving a constant ID. This allows
|
|
||||||
you to animate labels. For example, you may want to include varying information in a window title bar,
|
|
||||||
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
|
|
||||||
```cpp
|
|
||||||
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
|
|
||||||
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label
|
|
||||||
|
|
||||||
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
|
||||||
Begin(buf); // Variable title, ID = hash of "MyGame"
|
|
||||||
```
|
|
||||||
- Solving ID conflict in a more general manner:
|
- Solving ID conflict in a more general manner:
|
||||||
Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
|
Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
|
||||||
within the same window. This is the most convenient way of distinguishing ID when iterating and
|
within the same window. This is the most convenient way of distinguishing ID when iterating and
|
||||||
|
|||||||
@ -55,8 +55,8 @@ if (ImGui::Button("Save"))
|
|||||||
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
ImGui::InputText("string", buf, IM_COUNTOF(buf));
|
||||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||||
```
|
```
|
||||||

|
<img width="412" height="236" alt="sample code output (dark)" src="https://github.com/user-attachments/assets/32b838df-6378-498b-84a8-9a79ee6264a7" />
|
||||||

|
<img width="412" height="236" alt="sample code output (light)" src="https://github.com/user-attachments/assets/f075e2b0-98de-4be8-acb4-99ba0c9966cd" />
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Create a window called "My First Tool", with a menu bar.
|
// Create a window called "My First Tool", with a menu bar.
|
||||||
@ -90,7 +90,7 @@ for (int n = 0; n < 50; n++)
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
```
|
```
|
||||||

|

|
||||||
|
|
||||||
Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweak variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game-making editor/framework, etc.
|
Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweak variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game-making editor/framework, etc.
|
||||||
|
|
||||||
@ -110,11 +110,23 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
|
|||||||
### Demo
|
### Demo
|
||||||
|
|
||||||
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
|
Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
|
||||||
- [Web version of the demo](https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html) courtesy of [@pthom](https://github.com/pthom).
|
- [imgui_explorer](https://pthom.github.io/imgui_explorer): Web version of the demo w/ source code browser, courtesy of [@pthom](https://github.com/pthom).
|
||||||
- [Screenshot of the demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
|
|
||||||
|
|
||||||
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
|
You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
|
||||||
- [imgui-demo-binaries-20250625.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20250625.zip) (Windows, 1.92.0, built 2025/06/25, master) or [older binaries](https://www.dearimgui.com/binaries).
|
- [imgui-demo-binaries-20260225.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20260225.zip) (Windows, 1.92.6, built 2026/02/25, master) or [older binaries](https://www.dearimgui.com/binaries).
|
||||||
|
|
||||||
|
### Gallery
|
||||||
|
|
||||||
|
Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui).
|
||||||
|
|
||||||
|
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
|
||||||
|
|
||||||
|
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|--|--|
|
||||||
|
| Custom engine [erhe](https://github.com/tksuoran/erhe) (docking branch)<BR>[](https://user-images.githubusercontent.com/994606/147875067-a848991e-2ad2-4fd3-bf71-4aeb8a547bcf.png) | Custom engine for [Wonder Boy: The Dragon's Trap](http://www.TheDragonsTrap.com) (2017)<BR>[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) |
|
||||||
|
| Custom engine (untitled)<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) | Tracy Profiler ([github](https://github.com/wolfpld/tracy))<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png) |
|
||||||
|
|
||||||
### Getting Started & Integration
|
### Getting Started & Integration
|
||||||
|
|
||||||
@ -139,23 +151,12 @@ Officially maintained backends (in repository):
|
|||||||
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
|
- Many bindings are auto-generated (by good old [cimgui](https://github.com/cimgui/cimgui) or our newer [dear_bindings](https://github.com/dearimgui/dear_bindings)), you can use their metadata output to generate bindings for other languages.
|
||||||
|
|
||||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||||
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
|
||||||
|
[](https://github.com/ocornut/imgui/wiki/Useful-Extensions)
|
||||||
|
- Automation/testing, Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos, etc. Notable and well supported extensions include [ImPlot](https://github.com/epezent/implot), [ImPlot3d](https://github.com/brenocq/implot3d) and [Dear ImGui Test Engine](https://github.com/ocornut/imgui_test_engine).
|
||||||
|
|
||||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||||
|
|
||||||
### Gallery
|
|
||||||
|
|
||||||
Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui).
|
|
||||||
|
|
||||||
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)!
|
|
||||||
|
|
||||||
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|--|--|
|
|
||||||
| Custom engine [erhe](https://github.com/tksuoran/erhe) (docking branch)<BR>[](https://user-images.githubusercontent.com/994606/147875067-a848991e-2ad2-4fd3-bf71-4aeb8a547bcf.png) | Custom engine for [Wonder Boy: The Dragon's Trap](http://www.TheDragonsTrap.com) (2017)<BR>[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) |
|
|
||||||
| Custom engine (untitled)<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) | Tracy Profiler ([github](https://github.com/wolfpld/tracy))<BR>[](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png) |
|
|
||||||
|
|
||||||
### Support, Frequently Asked Questions (FAQ)
|
### Support, Frequently Asked Questions (FAQ)
|
||||||
|
|
||||||
See: [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) where common questions are answered.
|
See: [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) where common questions are answered.
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
# Building for desktop (WebGPU-native) with Dawn:
|
# Building for desktop with Dawn:
|
||||||
# 1. git clone https://github.com/google/dawn dawn
|
# 1. git clone https://github.com/google/dawn dawn
|
||||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_glfw_wgpu[.exe]
|
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||||
# * build/example_glfw_wgpu[.exe]
|
|
||||||
|
|
||||||
# Building for desktop (WGPU-Native) with WGPU-Native:
|
# Building for desktop with WGPU-Native:
|
||||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||||
# 2. unzip the downloaded file in your_preferred_folder
|
# 2. unzip the downloaded file in your_preferred_folder
|
||||||
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||||
# 4. cmake --build build
|
# 4. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_glfw_wgpu[.exe]
|
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||||
# * build/example_glfw_wgpu[.exe]
|
|
||||||
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
|
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||||
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
|
# 3. cmake --build build
|
||||||
|
# The resulting binary will be found at one of the following locations:
|
||||||
|
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
# Building for Emscripten:
|
# Building for Emscripten:
|
||||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||||
@ -52,35 +57,28 @@ set(IMGUI_EXAMPLE_SOURCE_FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
|
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Default to --use-port=emdawnwebgpu. You can override to provide your own local port.")
|
||||||
else()
|
else()
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
|
|
||||||
endif()
|
|
||||||
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
|
|
||||||
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
|
if(NOT IMGUI_EMSCRIPTEN_GLFW3)
|
||||||
|
# Defaults to contrib.glfw3 because Emscripten version is > 3.1.57
|
||||||
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
||||||
else() # cannot use contrib.glfw3 prior to 3.1.57
|
|
||||||
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)
|
||||||
else() # Native/Desktop build
|
else() # Native/Desktop build
|
||||||
# Check DAWN/WGPU directory
|
|
||||||
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
|
|
||||||
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
|
# Check DAWN/WGPU/WGVK directory
|
||||||
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
|
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
|
||||||
|
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
|
||||||
|
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
|
endif()
|
||||||
|
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
|
||||||
|
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
||||||
@ -90,7 +88,7 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
find_package(glfw3 REQUIRED)
|
find_package(glfw3 REQUIRED)
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR) # DAWN-Native build options
|
if(IMGUI_DAWN_DIR)
|
||||||
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
||||||
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
||||||
if(Dawn_FOUND)
|
if(Dawn_FOUND)
|
||||||
@ -133,7 +131,9 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES webgpu_dawn glfw)
|
set(LIBRARIES webgpu_dawn glfw)
|
||||||
endif()
|
endif()
|
||||||
else() # WGPU-Native build options
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||||
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@ -144,6 +144,9 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||||
@ -165,7 +168,6 @@ endif()
|
|||||||
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
|
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
|
||||||
# EMSCRIPTEN: by used FLAG
|
# EMSCRIPTEN: by used FLAG
|
||||||
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||||
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
|
||||||
# NATIVE: by used SDK installation directory
|
# NATIVE: by used SDK installation directory
|
||||||
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||||
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
||||||
@ -177,10 +179,20 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
|||||||
if(NOT Dawn_FOUND)
|
if(NOT Dawn_FOUND)
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
||||||
endif()
|
endif()
|
||||||
else()
|
endif()
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||||
endif()
|
endif()
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
|
||||||
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
|
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES})
|
||||||
|
|
||||||
else() # Emscripten settings
|
else() # Emscripten settings
|
||||||
@ -191,12 +203,8 @@ else() # Emscripten settings
|
|||||||
endif()
|
endif()
|
||||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
||||||
|
|
||||||
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||||
else()
|
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
|
||||||
endif()
|
|
||||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||||
|
|
||||||
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
|
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
|
||||||
|
|||||||
@ -19,8 +19,8 @@ WEB_DIR = web
|
|||||||
EXE = $(WEB_DIR)/index.html
|
EXE = $(WEB_DIR)/index.html
|
||||||
IMGUI_DIR = ../..
|
IMGUI_DIR = ../..
|
||||||
SOURCES = main.cpp
|
SOURCES = main.cpp
|
||||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
|
||||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
||||||
|
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
CPPFLAGS =
|
CPPFLAGS =
|
||||||
@ -40,11 +40,7 @@ LDFLAGS += -s ASYNCIFY=1
|
|||||||
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||||
LDFLAGS += -s ASSERTIONS=1
|
LDFLAGS += -s ASSERTIONS=1
|
||||||
|
|
||||||
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
# Using Dawn-based WebGPU port (requires 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)
|
|
||||||
EMS += --use-port=emdawnwebgpu
|
EMS += --use-port=emdawnwebgpu
|
||||||
LDFLAGS += --use-port=emdawnwebgpu
|
LDFLAGS += --use-port=emdawnwebgpu
|
||||||
|
|
||||||
|
|||||||
@ -60,14 +60,10 @@ For the WASM code produced by Emscripten to work correctly, it will also be nece
|
|||||||
CMake checks the EMSCRIPEN version then:
|
CMake checks the EMSCRIPEN version then:
|
||||||
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
|
- if EMS < 4.0.10 the build aborts (`-sUSE_WEBGPU=1` is no longer supported by our examples and our WGPU backend)
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
|
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||||
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||||
|
|||||||
@ -19,9 +19,6 @@
|
|||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
#include <emscripten/html5_webgpu.h>
|
|
||||||
#endif
|
|
||||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -68,8 +65,8 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
|
||||||
wgpu_surface_width *= main_scale;
|
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
|
||||||
wgpu_surface_height *= main_scale;
|
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
|
||||||
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
|
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;
|
||||||
@ -344,20 +341,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
|
|||||||
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||||
return acquired_device.MoveToCHandle();
|
return acquired_device.MoveToCHandle();
|
||||||
}
|
}
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
// Adapter and device initialization via JS
|
|
||||||
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
|
|
||||||
{
|
|
||||||
if (!navigator.gpu)
|
|
||||||
throw Error("WebGPU not supported.");
|
|
||||||
const adapter = await navigator.gpu.requestAdapter();
|
|
||||||
const device = await adapter.requestDevice();
|
|
||||||
Module.preinitializedWebGPUDevice = device;
|
|
||||||
} );
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestAdapterStatus_Success)
|
if (status == WGPURequestAdapterStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||||
@ -371,6 +358,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
|
|||||||
|
|
||||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestDeviceStatus_Success)
|
if (status == WGPURequestDeviceStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||||
@ -386,27 +374,32 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
|||||||
{
|
{
|
||||||
WGPURequestAdapterOptions adapter_options = {};
|
WGPURequestAdapterOptions adapter_options = {};
|
||||||
|
|
||||||
WGPUAdapter local_adapter;
|
WGPUAdapter local_adapter = nullptr;
|
||||||
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||||
|
adapterCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
adapterCallbackInfo.callback = handle_request_adapter;
|
adapterCallbackInfo.callback = handle_request_adapter;
|
||||||
adapterCallbackInfo.userdata1 = &local_adapter;
|
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||||
|
|
||||||
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||||
return local_adapter;
|
return local_adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
||||||
{
|
{
|
||||||
WGPUDevice local_device;
|
WGPUDevice local_device = nullptr;
|
||||||
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||||
|
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
deviceCallbackInfo.callback = handle_request_device;
|
deviceCallbackInfo.callback = handle_request_device;
|
||||||
deviceCallbackInfo.userdata1 = &local_device;
|
deviceCallbackInfo.userdata1 = &local_device;
|
||||||
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_device && "Error on Device request");
|
IM_ASSERT(local_device && "Error on Device request");
|
||||||
return local_device;
|
return local_device;
|
||||||
}
|
}
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
bool InitWGPU(GLFWwindow* window)
|
bool InitWGPU(GLFWwindow* window)
|
||||||
@ -449,35 +442,24 @@ bool InitWGPU(GLFWwindow* window)
|
|||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
|
|
||||||
// WGPU backend: Adapter and Device acquisition, Surface creation
|
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
wgpu_instance = wgpuCreateInstance(nullptr);
|
WGPUInstanceDescriptor instanceDesc = {};
|
||||||
|
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
|
||||||
|
instanceDesc.requiredFeatureCount = 1;
|
||||||
|
instanceDesc.requiredFeatures = &timedWaitAny;
|
||||||
|
wgpu_instance = wgpuCreateInstance(&instanceDesc);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
getAdapterAndDeviceViaJS();
|
|
||||||
|
|
||||||
wgpu_device = emscripten_webgpu_get_device();
|
|
||||||
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
|
||||||
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
|
||||||
html_surface_desc.selector = "#canvas";
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptor surface_desc = {};
|
|
||||||
surface_desc.nextInChain = &html_surface_desc.chain;
|
|
||||||
|
|
||||||
// Create the surface.
|
|
||||||
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
|
|
||||||
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
wgpuSetLogCallback(
|
wgpuSetLogCallback(
|
||||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||||
);
|
);
|
||||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||||
|
#endif
|
||||||
|
|
||||||
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||||
|
|
||||||
wgpu_device = RequestDevice(adapter);
|
wgpu_device = RequestDevice(wgpu_instance, adapter);
|
||||||
|
|
||||||
// Create the surface.
|
// Create the surface.
|
||||||
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||||
@ -488,7 +470,6 @@ bool InitWGPU(GLFWwindow* window)
|
|||||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||||
|
|
||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||||
@ -573,7 +554,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error "Unsupported WebGPU native platform!"
|
#error "Unsupported WebGPU native platform!"
|
||||||
#endif
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // #ifndef __EMSCRIPTEN__
|
#endif // #ifndef __EMSCRIPTEN__
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
# Building for desktop (WebGPU-native) with Dawn:
|
# Building for desktop with Dawn:
|
||||||
# 1. git clone https://github.com/google/dawn dawn
|
# 1. git clone https://github.com/google/dawn dawn
|
||||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_sdl2_wgpu[.exe]
|
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||||
# * build/example_sdl2_wgpu[.exe]
|
|
||||||
|
|
||||||
# Building for desktop (WGPU-Native) with WGPU-Native:
|
# Building for desktop with WGPU-Native:
|
||||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||||
# 2. unzip the downloaded file in your_preferred_folder
|
# 2. unzip the downloaded file in your_preferred_folder
|
||||||
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||||
# 4. cmake --build build
|
# 4. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_sdl2_wgpu[.exe]
|
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||||
# * build/example_sdl2_wgpu[.exe]
|
|
||||||
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
|
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||||
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
|
# 3. cmake --build build
|
||||||
|
# The resulting binary will be found at one of the following locations:
|
||||||
|
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||||
|
|
||||||
# Building for Emscripten:
|
# Building for Emscripten:
|
||||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||||
@ -52,27 +57,22 @@ set(IMGUI_EXAMPLE_SOURCE_FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
|
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Default to --use-port=emdawnwebgpu. You can override to provide your own local port.")
|
||||||
else()
|
else()
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
|
|
||||||
endif()
|
|
||||||
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
|
|
||||||
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||||
else() # Native/Desktop build
|
else() # Native/Desktop build
|
||||||
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
|
|
||||||
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
|
# Check DAWN/WGPU/WGVK directory
|
||||||
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
|
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
|
||||||
|
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
|
||||||
|
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
|
endif()
|
||||||
|
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
|
||||||
|
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
||||||
@ -82,7 +82,7 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
|
find_package(SDL2 REQUIRED) # SDL_MAIN_HANDLED
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR) # DAWN-Native build options
|
if(IMGUI_DAWN_DIR)
|
||||||
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
||||||
find_package(Threads) # required from Dawn installation
|
find_package(Threads) # required from Dawn installation
|
||||||
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
||||||
@ -126,8 +126,9 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
|
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
else() # WGPU-Native build options
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||||
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@ -138,6 +139,10 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||||
@ -160,7 +165,6 @@ endif()
|
|||||||
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
|
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
|
||||||
# EMSCRIPTEN: by used FLAG
|
# EMSCRIPTEN: by used FLAG
|
||||||
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
|
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
|
||||||
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
|
|
||||||
# NATIVE: by used SDK installation directory
|
# NATIVE: by used SDK installation directory
|
||||||
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
|
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
|
||||||
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
|
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
|
||||||
@ -171,21 +175,26 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
|||||||
if(NOT Dawn_FOUND)
|
if(NOT Dawn_FOUND)
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
||||||
endif()
|
endif()
|
||||||
else()
|
endif()
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||||
endif()
|
endif()
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
|
||||||
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
|
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} ${SDL2_LIBRARIES})
|
||||||
else() # Emscripten settings
|
else() # Emscripten settings
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||||
|
|
||||||
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||||
else()
|
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
|
||||||
endif()
|
|
||||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||||
|
|
||||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=2")
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=2")
|
||||||
|
|||||||
@ -19,8 +19,8 @@ WEB_DIR = web
|
|||||||
EXE = $(WEB_DIR)/index.html
|
EXE = $(WEB_DIR)/index.html
|
||||||
IMGUI_DIR = ../..
|
IMGUI_DIR = ../..
|
||||||
SOURCES = main.cpp
|
SOURCES = main.cpp
|
||||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
|
||||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
||||||
|
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
CPPFLAGS =
|
CPPFLAGS =
|
||||||
@ -40,11 +40,7 @@ LDFLAGS += -s ASYNCIFY=1
|
|||||||
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||||
LDFLAGS += -s ASSERTIONS=1
|
LDFLAGS += -s ASSERTIONS=1
|
||||||
|
|
||||||
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
# Using Dawn-based WebGPU port (requires 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)
|
|
||||||
EMS += --use-port=emdawnwebgpu
|
EMS += --use-port=emdawnwebgpu
|
||||||
LDFLAGS += --use-port=emdawnwebgpu
|
LDFLAGS += --use-port=emdawnwebgpu
|
||||||
|
|
||||||
|
|||||||
@ -60,14 +60,10 @@ For the WASM code produced by Emscripten to work correctly, it will also be nece
|
|||||||
CMake checks the EMSCRIPEN version then:
|
CMake checks the EMSCRIPEN version then:
|
||||||
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
|
- if EMS < 4.0.10 the build aborts (`-sUSE_WEBGPU=1` is no longer supported by our examples and our WGPU backend)
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
|
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||||
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||||
|
|||||||
@ -18,9 +18,6 @@
|
|||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
#include <emscripten/html5_webgpu.h>
|
|
||||||
#endif
|
|
||||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -56,7 +53,9 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Create window with graphics context
|
// Create window with graphics context
|
||||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||||
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
|
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
|
||||||
|
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
|
||||||
|
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+WebGPU example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wgpu_surface_width, wgpu_surface_height, window_flags);
|
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+WebGPU example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wgpu_surface_width, wgpu_surface_height, window_flags);
|
||||||
if (window == nullptr)
|
if (window == nullptr)
|
||||||
{
|
{
|
||||||
@ -146,7 +145,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// React to changes in screen size
|
// React to changes in screen size
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSize(window, &width, &height);
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||||
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||||
ResizeSurface(width, height);
|
ResizeSurface(width, height);
|
||||||
|
|
||||||
@ -327,20 +326,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
|
|||||||
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||||
return acquired_device.MoveToCHandle();
|
return acquired_device.MoveToCHandle();
|
||||||
}
|
}
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
// Adapter and device initialization via JS
|
|
||||||
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
|
|
||||||
{
|
|
||||||
if (!navigator.gpu)
|
|
||||||
throw Error("WebGPU not supported.");
|
|
||||||
const adapter = await navigator.gpu.requestAdapter();
|
|
||||||
const device = await adapter.requestDevice();
|
|
||||||
Module.preinitializedWebGPUDevice = device;
|
|
||||||
} );
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestAdapterStatus_Success)
|
if (status == WGPURequestAdapterStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||||
@ -354,6 +343,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
|
|||||||
|
|
||||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestDeviceStatus_Success)
|
if (status == WGPURequestDeviceStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||||
@ -369,27 +359,32 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
|||||||
{
|
{
|
||||||
WGPURequestAdapterOptions adapter_options = {};
|
WGPURequestAdapterOptions adapter_options = {};
|
||||||
|
|
||||||
WGPUAdapter local_adapter;
|
WGPUAdapter local_adapter = nullptr;
|
||||||
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||||
|
adapterCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
adapterCallbackInfo.callback = handle_request_adapter;
|
adapterCallbackInfo.callback = handle_request_adapter;
|
||||||
adapterCallbackInfo.userdata1 = &local_adapter;
|
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||||
|
|
||||||
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||||
return local_adapter;
|
return local_adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
||||||
{
|
{
|
||||||
WGPUDevice local_device;
|
WGPUDevice local_device = nullptr;
|
||||||
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||||
|
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
deviceCallbackInfo.callback = handle_request_device;
|
deviceCallbackInfo.callback = handle_request_device;
|
||||||
deviceCallbackInfo.userdata1 = &local_device;
|
deviceCallbackInfo.userdata1 = &local_device;
|
||||||
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_device && "Error on Device request");
|
IM_ASSERT(local_device && "Error on Device request");
|
||||||
return local_device;
|
return local_device;
|
||||||
}
|
}
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
static bool InitWGPU(SDL_Window* window)
|
static bool InitWGPU(SDL_Window* window)
|
||||||
@ -433,35 +428,24 @@ static bool InitWGPU(SDL_Window* window)
|
|||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
|
|
||||||
// WGPU backend: Adapter and Device acquisition, Surface creation
|
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
wgpu_instance = wgpuCreateInstance(nullptr);
|
WGPUInstanceDescriptor instanceDesc = {};
|
||||||
|
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
|
||||||
|
instanceDesc.requiredFeatureCount = 1;
|
||||||
|
instanceDesc.requiredFeatures = &timedWaitAny;
|
||||||
|
wgpu_instance = wgpuCreateInstance(&instanceDesc);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
getAdapterAndDeviceViaJS();
|
|
||||||
|
|
||||||
wgpu_device = emscripten_webgpu_get_device();
|
|
||||||
assert(wgpu_device != nullptr && "Error creating the Device");
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
|
||||||
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
|
||||||
html_surface_desc.selector = "#canvas";
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptor surface_desc = {};
|
|
||||||
surface_desc.nextInChain = &html_surface_desc.chain;
|
|
||||||
|
|
||||||
// Create the surface.
|
|
||||||
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
|
|
||||||
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
wgpuSetLogCallback(
|
wgpuSetLogCallback(
|
||||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||||
);
|
);
|
||||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||||
|
#endif
|
||||||
|
|
||||||
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||||
|
|
||||||
wgpu_device = RequestDevice(adapter);
|
wgpu_device = RequestDevice(wgpu_instance, adapter);
|
||||||
|
|
||||||
// Create the surface.
|
// Create the surface.
|
||||||
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||||
@ -472,7 +456,6 @@ static bool InitWGPU(SDL_Window* window)
|
|||||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||||
|
|
||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||||
@ -537,7 +520,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error "Unsupported WebGPU native platform!"
|
#error "Unsupported WebGPU native platform!"
|
||||||
#endif
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // #ifndef __EMSCRIPTEN__
|
#endif // #ifndef __EMSCRIPTEN__
|
||||||
|
|||||||
@ -1,19 +1,24 @@
|
|||||||
# Building for desktop (WebGPU-native) with Dawn:
|
# Building for desktop with Dawn:
|
||||||
# 1. git clone https://github.com/google/dawn dawn
|
# 1. git clone https://github.com/google/dawn dawn
|
||||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_sdl3_wgpu[.exe]
|
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
|
||||||
# * build/example_sdl3_wgpu[.exe]
|
|
||||||
|
|
||||||
# Building for desktop (WGPU-Native) with WGPU-Native:
|
# Building for desktop with WGPU-Native:
|
||||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||||
# 2. unzip the downloaded file in your_preferred_folder
|
# 2. unzip the downloaded file in your_preferred_folder
|
||||||
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||||
# 4. cmake --build build
|
# 4. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
# * build/Debug/example_sdl3_wgpu[.exe]
|
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
|
||||||
# * build/example_sdl3_wgpu[.exe]
|
|
||||||
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
|
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||||
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
|
# 3. cmake --build build
|
||||||
|
# The resulting binary will be found at one of the following locations:
|
||||||
|
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
|
||||||
|
|
||||||
# Building for Emscripten:
|
# Building for Emscripten:
|
||||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||||
@ -55,27 +60,19 @@ if(EMSCRIPTEN)
|
|||||||
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.15")
|
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.15")
|
||||||
message(FATAL_ERROR "Using Emscripten with SDL3 needs Emscripten version >= 4.0.15")
|
message(FATAL_ERROR "Using Emscripten with SDL3 needs Emscripten version >= 4.0.15")
|
||||||
endif()
|
endif()
|
||||||
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
|
# emdawnwebgpu was introduced in 4.0.10 so, due to the prior requirement, this will work
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Default to --use-port=emdawnwebgpu. You can override to provide your own local port.")
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
|
|
||||||
else()
|
|
||||||
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
|
|
||||||
endif()
|
|
||||||
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
|
|
||||||
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
|
|
||||||
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||||
else() # Native/Desktop build
|
else() # Native/Desktop build
|
||||||
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
|
|
||||||
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
|
# Check DAWN/WGPU/WGVK directory
|
||||||
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
|
# If it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR or IMGUI_WGVK_DIR must be specified
|
||||||
|
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR AND NOT IMGUI_WGVK_DIR)
|
||||||
|
message(FATAL_ERROR "Please specify one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
|
endif()
|
||||||
|
if((IMGUI_DAWN_DIR AND (IMGUI_WGPU_DIR OR IMGUI_WGVK_DIR)) OR (IMGUI_WGPU_DIR AND IMGUI_WGVK_DIR))
|
||||||
|
message(FATAL_ERROR "Please specify only one of IMGUI_DAWN_DIR/IMGUI_WGPU_DIR/IMGUI_WGVK_DIR base directory.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE) # Add SDL3 module to get Surface, with libs and file property for MacOS build
|
if(APPLE) # Add SDL3 module to get Surface, with libs and file property for MacOS build
|
||||||
@ -85,7 +82,7 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
|
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
|
||||||
|
|
||||||
if(IMGUI_DAWN_DIR) # DAWN-Native build options
|
if(IMGUI_DAWN_DIR)
|
||||||
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
list(APPEND CMAKE_PREFIX_PATH ${IMGUI_DAWN_DIR})
|
||||||
find_package(Threads) # required from Dawn installation
|
find_package(Threads) # required from Dawn installation
|
||||||
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
find_package(Dawn) # Search for a Dawn installation using IMGUI_DAWN_DIR in CMAKE_PREFIX_PATH
|
||||||
@ -129,7 +126,9 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
|
set(LIBRARIES webgpu_dawn ${OS_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
else() # WGPU-Native build options
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||||
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@ -140,6 +139,9 @@ else() # Native/Desktop build
|
|||||||
|
|
||||||
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
set(LIBRARIES ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||||
@ -162,7 +164,6 @@ endif()
|
|||||||
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
|
# IMGUI_IMPL_WEBGPU_BACKEND_DAWN/WGPU internal define is set according to:
|
||||||
# EMSCRIPTEN: by used FLAG
|
# EMSCRIPTEN: by used FLAG
|
||||||
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
|
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled (+EMSCRIPTEN)
|
||||||
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled (+EMSCRIPTEN)
|
|
||||||
# NATIVE: by used SDK installation directory
|
# NATIVE: by used SDK installation directory
|
||||||
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
|
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN enabled
|
||||||
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
|
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU enabled
|
||||||
@ -173,21 +174,26 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
|||||||
if(NOT Dawn_FOUND)
|
if(NOT Dawn_FOUND)
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp)
|
||||||
endif()
|
endif()
|
||||||
else()
|
endif()
|
||||||
|
if(IMGUI_WGPU_DIR)
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||||
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||||
endif()
|
endif()
|
||||||
|
if(IMGUI_WGVK_DIR)
|
||||||
|
target_sources(${IMGUI_EXECUTABLE} PRIVATE ${IMGUI_WGVK_DIR}/src/wgvk.c)
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGVK")
|
||||||
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} SDL3::SDL3)
|
target_link_libraries(${IMGUI_EXECUTABLE} PUBLIC ${LIBRARIES} SDL3::SDL3)
|
||||||
else() # Emscripten settings
|
else() # Emscripten settings
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||||
|
|
||||||
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
|
||||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||||
else()
|
|
||||||
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
|
||||||
endif()
|
|
||||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||||
|
|
||||||
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=3")
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "-sUSE_SDL=3")
|
||||||
|
|||||||
@ -19,8 +19,8 @@ WEB_DIR = web
|
|||||||
EXE = $(WEB_DIR)/index.html
|
EXE = $(WEB_DIR)/index.html
|
||||||
IMGUI_DIR = ../..
|
IMGUI_DIR = ../..
|
||||||
SOURCES = main.cpp
|
SOURCES = main.cpp
|
||||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
|
||||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
|
||||||
|
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
CPPFLAGS =
|
CPPFLAGS =
|
||||||
@ -40,11 +40,7 @@ LDFLAGS += -s ASYNCIFY=1
|
|||||||
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||||
LDFLAGS += -s ASSERTIONS=1
|
LDFLAGS += -s ASSERTIONS=1
|
||||||
|
|
||||||
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
# Using Dawn-based WebGPU port (requires 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)
|
|
||||||
EMS += --use-port=emdawnwebgpu
|
EMS += --use-port=emdawnwebgpu
|
||||||
LDFLAGS += --use-port=emdawnwebgpu
|
LDFLAGS += --use-port=emdawnwebgpu
|
||||||
|
|
||||||
|
|||||||
@ -60,14 +60,10 @@ For the WASM code produced by Emscripten to work correctly, it will also be nece
|
|||||||
CMake checks the EMSCRIPEN version then:
|
CMake checks the EMSCRIPEN version then:
|
||||||
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
|
- if EMS < 4.0.10 the build aborts (`-sUSE_WEBGPU=1` is no longer supported by our examples and our WGPU backend
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
|
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
|
||||||
|
|
||||||
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||||
|
|
||||||
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||||
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||||
|
|||||||
@ -20,9 +20,6 @@
|
|||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
#include <emscripten/html5_webgpu.h>
|
|
||||||
#endif
|
|
||||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -64,6 +61,8 @@ int main(int, char**)
|
|||||||
// Create SDL window graphics context
|
// Create SDL window graphics context
|
||||||
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||||
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
|
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE;
|
||||||
|
wgpu_surface_width = (int)(wgpu_surface_width * main_scale);
|
||||||
|
wgpu_surface_height = (int)(wgpu_surface_height * main_scale);
|
||||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+WebGPU example", wgpu_surface_width, wgpu_surface_height, window_flags);
|
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+WebGPU example", wgpu_surface_width, wgpu_surface_height, window_flags);
|
||||||
if (window == nullptr)
|
if (window == nullptr)
|
||||||
{
|
{
|
||||||
@ -338,20 +337,10 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
|
|||||||
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||||
return acquired_device.MoveToCHandle();
|
return acquired_device.MoveToCHandle();
|
||||||
}
|
}
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
// Adapter and device initialization via JS
|
|
||||||
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
|
|
||||||
{
|
|
||||||
if (!navigator.gpu)
|
|
||||||
throw Error("WebGPU not supported.");
|
|
||||||
const adapter = await navigator.gpu.requestAdapter();
|
|
||||||
const device = await adapter.requestDevice();
|
|
||||||
Module.preinitializedWebGPUDevice = device;
|
|
||||||
} );
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestAdapterStatus_Success)
|
if (status == WGPURequestAdapterStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||||
@ -365,6 +354,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter
|
|||||||
|
|
||||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
{
|
{
|
||||||
|
IM_UNUSED(userdata2);
|
||||||
if (status == WGPURequestDeviceStatus_Success)
|
if (status == WGPURequestDeviceStatus_Success)
|
||||||
{
|
{
|
||||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||||
@ -380,27 +370,32 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
|||||||
{
|
{
|
||||||
WGPURequestAdapterOptions adapter_options = {};
|
WGPURequestAdapterOptions adapter_options = {};
|
||||||
|
|
||||||
WGPUAdapter local_adapter;
|
WGPUAdapter local_adapter = nullptr;
|
||||||
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||||
|
adapterCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
adapterCallbackInfo.callback = handle_request_adapter;
|
adapterCallbackInfo.callback = handle_request_adapter;
|
||||||
adapterCallbackInfo.userdata1 = &local_adapter;
|
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||||
|
|
||||||
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||||
return local_adapter;
|
return local_adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
||||||
{
|
{
|
||||||
WGPUDevice local_device;
|
WGPUDevice local_device = nullptr;
|
||||||
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||||
|
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||||
deviceCallbackInfo.callback = handle_request_device;
|
deviceCallbackInfo.callback = handle_request_device;
|
||||||
deviceCallbackInfo.userdata1 = &local_device;
|
deviceCallbackInfo.userdata1 = &local_device;
|
||||||
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||||
|
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||||
|
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||||
IM_ASSERT(local_device && "Error on Device request");
|
IM_ASSERT(local_device && "Error on Device request");
|
||||||
return local_device;
|
return local_device;
|
||||||
}
|
}
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
static bool InitWGPU(SDL_Window* window)
|
static bool InitWGPU(SDL_Window* window)
|
||||||
@ -444,35 +439,24 @@ static bool InitWGPU(SDL_Window* window)
|
|||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
|
|
||||||
// WGPU backend: Adapter and Device acquisition, Surface creation
|
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||||
wgpu_instance = wgpuCreateInstance(nullptr);
|
WGPUInstanceDescriptor instanceDesc = {};
|
||||||
|
WGPUInstanceFeatureName timedWaitAny = WGPUInstanceFeatureName_TimedWaitAny;
|
||||||
|
instanceDesc.requiredFeatureCount = 1;
|
||||||
|
instanceDesc.requiredFeatures = &timedWaitAny;
|
||||||
|
wgpu_instance = wgpuCreateInstance(&instanceDesc);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
getAdapterAndDeviceViaJS();
|
|
||||||
|
|
||||||
wgpu_device = emscripten_webgpu_get_device();
|
|
||||||
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
|
||||||
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
|
||||||
html_surface_desc.selector = "#canvas";
|
|
||||||
|
|
||||||
WGPUSurfaceDescriptor surface_desc = {};
|
|
||||||
surface_desc.nextInChain = &html_surface_desc.chain;
|
|
||||||
|
|
||||||
// Create the surface.
|
|
||||||
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
|
|
||||||
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
|
|
||||||
#else // __EMSCRIPTEN__
|
|
||||||
wgpuSetLogCallback(
|
wgpuSetLogCallback(
|
||||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||||
);
|
);
|
||||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||||
|
#endif
|
||||||
|
|
||||||
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||||
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||||
|
|
||||||
wgpu_device = RequestDevice(adapter);
|
wgpu_device = RequestDevice(wgpu_instance, adapter);
|
||||||
|
|
||||||
// Create the surface.
|
// Create the surface.
|
||||||
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||||
@ -483,7 +467,6 @@ static bool InitWGPU(SDL_Window* window)
|
|||||||
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||||
|
|
||||||
preferred_fmt = surface_capabilities.formats[0];
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
#endif // __EMSCRIPTEN__
|
|
||||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||||
@ -513,7 +496,7 @@ static bool InitWGPU(SDL_Window* window)
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
|
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* window)
|
||||||
{
|
{
|
||||||
SDL_PropertiesID propertiesID = SDL_GetWindowProperties(window);
|
SDL_PropertiesID propertiesID = SDL_GetWindowProperties(window);
|
||||||
|
|
||||||
@ -549,7 +532,7 @@ static WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, SDL_Window* w
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error "Unsupported WebGPU native platform!"
|
#error "Unsupported WebGPU native platform!"
|
||||||
#endif
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // #ifndef __EMSCRIPTEN__
|
#endif // #ifndef __EMSCRIPTEN__
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||||
<title>Dear ImGui Emscripten example</title>
|
<title>Dear ImGui Emscripten example</title>
|
||||||
<style>
|
<style>
|
||||||
body { margin: 0; background-color: black }
|
body { margin: 0; background-color: black; overflow: hidden; }
|
||||||
/* FIXME: with our GLFW example this block seems to break resizing and io.DisplaySize gets stuck */
|
/* FIXME: with our GLFW example this block seems to break resizing and io.DisplaySize gets stuck */
|
||||||
.emscripten {
|
.emscripten {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -26,10 +26,13 @@
|
|||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
-ms-interpolation-mode: nearest-neighbor;
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
}
|
}
|
||||||
|
#canvas:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
var Module = {
|
var Module = {
|
||||||
preRun: [],
|
preRun: [],
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (main code and documentation)
|
// (main code and documentation)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
@ -20,7 +20,7 @@
|
|||||||
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
|
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
|
||||||
// - Issues & support ........... https://github.com/ocornut/imgui/issues
|
// - Issues & support ........... https://github.com/ocornut/imgui/issues
|
||||||
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
|
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
|
||||||
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
|
// - Web version of the Demo .... https://pthom.github.io/imgui_explorer (w/ source code browser)
|
||||||
|
|
||||||
// For FIRST-TIME users having issues compiling/linking/running:
|
// For FIRST-TIME users having issues compiling/linking/running:
|
||||||
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
|
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
|
||||||
@ -168,6 +168,7 @@ CODE
|
|||||||
- Home, End Scroll to top, scroll to bottom.
|
- Home, End Scroll to top, scroll to bottom.
|
||||||
- Alt Toggle between scrolling layer and menu layer.
|
- Alt Toggle between scrolling layer and menu layer.
|
||||||
- Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving.
|
- Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving.
|
||||||
|
- Menu or Shift+F10 Open context menu.
|
||||||
- Output when ImGuiConfigFlags_NavEnableKeyboard set,
|
- Output when ImGuiConfigFlags_NavEnableKeyboard set,
|
||||||
- io.WantCaptureKeyboard flag is set when keyboard is claimed.
|
- io.WantCaptureKeyboard flag is set when keyboard is claimed.
|
||||||
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
|
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
|
||||||
@ -208,7 +209,7 @@ CODE
|
|||||||
The UI can be highly dynamic, there are no construction or destruction steps, less superfluous
|
The UI can be highly dynamic, there are no construction or destruction steps, less superfluous
|
||||||
data retention on your side, less state duplication, less state synchronization, fewer bugs.
|
data retention on your side, less state duplication, less state synchronization, fewer bugs.
|
||||||
- Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
|
- Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
|
||||||
Or browse https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html for interactive web version.
|
Or browse pthom's online imgui_explorer: https://pthom.github.io/imgui_explorer for a web version w/ source code browser.
|
||||||
- The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
|
- The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
|
||||||
- Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
|
- Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
|
||||||
You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki.
|
You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki.
|
||||||
@ -402,6 +403,19 @@ 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.
|
||||||
|
|
||||||
|
- 2026/03/19 (1.92.7) - MultiSelect: renamed ImGuiMultiSelectFlags_SelectOnClick to ImGuiMultiSelectFlags_SelectOnAuto.
|
||||||
|
- 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator.
|
||||||
|
The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
|
||||||
|
The "Console" example had such a bug:
|
||||||
|
float footer_height = style.ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||||
|
Should be:
|
||||||
|
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
BeginChild("ScrollingRegion", { 0, -footer_height });
|
||||||
|
When such idiom was used and assuming zero-height Separator, it is likely that in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
|
||||||
|
- 2026/02/23 (1.92.7) - Commented out legacy signature for Combo(), ListBox(), signatures which were obsoleted in 1.90 (Nov 2023), when the getter callback type was changed.
|
||||||
|
- Old getter type: bool (*getter)(void* user_data, int idx, const char** out_text) // Set label + return bool. False replaced label with placeholder.
|
||||||
|
- New getter type: const char* (*getter)(void* user_data, int idx) // Return label or NULL/empty label if missing
|
||||||
- 2026/01/08 (1.92.6) - Commented out legacy names obsoleted in 1.90 (Sept 2023): 'BeginChildFrame()' --> 'BeginChild()' with 'ImGuiChildFlags_FrameStyle'. 'EndChildFrame()' --> 'EndChild()'. 'ShowStackToolWindow()' --> 'ShowIDStackToolWindow()'. 'IM_OFFSETOF()' --> 'offsetof()'.
|
- 2026/01/08 (1.92.6) - Commented out legacy names obsoleted in 1.90 (Sept 2023): 'BeginChildFrame()' --> 'BeginChild()' with 'ImGuiChildFlags_FrameStyle'. 'EndChildFrame()' --> 'EndChild()'. 'ShowStackToolWindow()' --> 'ShowIDStackToolWindow()'. 'IM_OFFSETOF()' --> 'offsetof()'.
|
||||||
- 2026/01/07 (1.92.6) - Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). Default value has same meaning before and after.
|
- 2026/01/07 (1.92.6) - Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). Default value has same meaning before and after.
|
||||||
- Refer to GitHub topic #9157 if you have any question.
|
- Refer to GitHub topic #9157 if you have any question.
|
||||||
@ -1113,6 +1127,8 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|||||||
- Run the examples/ applications and explore them.
|
- Run the examples/ applications and explore them.
|
||||||
- Read Getting Started (https://github.com/ocornut/imgui/wiki/Getting-Started) guide.
|
- Read Getting Started (https://github.com/ocornut/imgui/wiki/Getting-Started) guide.
|
||||||
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
||||||
|
- See pthom's online imgui_explorer (https://pthom.github.io/imgui_explorer) which is a web
|
||||||
|
version of the demo with a source code browser.
|
||||||
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||||
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
||||||
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the
|
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the
|
||||||
@ -1149,10 +1165,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
Q: About the ID Stack system..
|
Q: About the ID Stack system..
|
||||||
- Why is my widget not reacting when I click on it?
|
- How can I have multiple widgets with the same label? (using ## or PushID)
|
||||||
- How can I have widgets with an empty label?
|
- How can I have widgets with an empty label? (using ##)
|
||||||
- How can I have multiple widgets with the same label?
|
- How can I make a label dynamic? (using ###)
|
||||||
- How can I have multiple windows with the same label?
|
- General description of the label and ID Stack system.
|
||||||
Q: How can I display an image? What is ImTextureID, how does it work?
|
Q: How can I display an image? What is ImTextureID, how does it work?
|
||||||
Q: How can I use my own math types instead of ImVec2?
|
Q: How can I use my own math types instead of ImVec2?
|
||||||
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
||||||
@ -1309,6 +1325,7 @@ static const float FONT_DEFAULT_SIZE_BASE = 20.0f;
|
|||||||
static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
|
static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
|
||||||
static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
|
static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
|
||||||
static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut.
|
static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut.
|
||||||
|
static const float NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY = 0.60f; // Time to hold activation button (e.g. FaceDown) to turn the activation into a text input.
|
||||||
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
|
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
|
||||||
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
|
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
|
||||||
|
|
||||||
@ -1358,6 +1375,7 @@ static void NavUpdateWindowing();
|
|||||||
static void NavUpdateWindowingApplyFocus(ImGuiWindow* window);
|
static void NavUpdateWindowingApplyFocus(ImGuiWindow* window);
|
||||||
static void NavUpdateWindowingOverlay();
|
static void NavUpdateWindowingOverlay();
|
||||||
static void NavUpdateCancelRequest();
|
static void NavUpdateCancelRequest();
|
||||||
|
static void NavUpdateContextMenuRequest();
|
||||||
static void NavUpdateCreateMoveRequest();
|
static void NavUpdateCreateMoveRequest();
|
||||||
static void NavUpdateCreateTabbingRequest();
|
static void NavUpdateCreateTabbingRequest();
|
||||||
static float NavUpdatePageUpPageDown();
|
static float NavUpdatePageUpPageDown();
|
||||||
@ -1523,7 +1541,8 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||||
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
|
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
|
||||||
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||||
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText()
|
SeparatorSize = 1.0f; // Thickness of border in Separator().
|
||||||
|
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText().
|
||||||
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||||
SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
||||||
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
|
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
|
||||||
@ -1560,11 +1579,15 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
|||||||
_MainScale *= scale_factor;
|
_MainScale *= scale_factor;
|
||||||
WindowPadding = ImTrunc(WindowPadding * scale_factor);
|
WindowPadding = ImTrunc(WindowPadding * scale_factor);
|
||||||
WindowRounding = ImTrunc(WindowRounding * scale_factor);
|
WindowRounding = ImTrunc(WindowRounding * scale_factor);
|
||||||
|
WindowBorderSize = ImTrunc(WindowBorderSize * scale_factor);
|
||||||
WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
|
WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
|
||||||
WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor);
|
WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor);
|
||||||
ChildRounding = ImTrunc(ChildRounding * scale_factor);
|
ChildRounding = ImTrunc(ChildRounding * scale_factor);
|
||||||
|
ChildBorderSize = ImTrunc(ChildBorderSize * scale_factor);
|
||||||
PopupRounding = ImTrunc(PopupRounding * scale_factor);
|
PopupRounding = ImTrunc(PopupRounding * scale_factor);
|
||||||
|
PopupBorderSize = ImTrunc(PopupBorderSize * scale_factor);
|
||||||
FramePadding = ImTrunc(FramePadding * scale_factor);
|
FramePadding = ImTrunc(FramePadding * scale_factor);
|
||||||
|
FrameBorderSize = ImTrunc(FrameBorderSize * scale_factor);
|
||||||
FrameRounding = ImTrunc(FrameRounding * scale_factor);
|
FrameRounding = ImTrunc(FrameRounding * scale_factor);
|
||||||
ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
|
ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
|
||||||
ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
|
ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
|
||||||
@ -1581,16 +1604,21 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
|||||||
ImageRounding = ImTrunc(ImageRounding * scale_factor);
|
ImageRounding = ImTrunc(ImageRounding * scale_factor);
|
||||||
ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
|
ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
|
||||||
TabRounding = ImTrunc(TabRounding * scale_factor);
|
TabRounding = ImTrunc(TabRounding * scale_factor);
|
||||||
|
TabBorderSize = ImTrunc(TabBorderSize * scale_factor);
|
||||||
TabMinWidthBase = ImTrunc(TabMinWidthBase * scale_factor);
|
TabMinWidthBase = ImTrunc(TabMinWidthBase * scale_factor);
|
||||||
TabMinWidthShrink = ImTrunc(TabMinWidthShrink * scale_factor);
|
TabMinWidthShrink = ImTrunc(TabMinWidthShrink * scale_factor);
|
||||||
TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected;
|
TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected;
|
||||||
TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected;
|
TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected;
|
||||||
|
TabBarBorderSize = ImTrunc(TabBarBorderSize * scale_factor);
|
||||||
TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
|
TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
|
||||||
|
TreeLinesSize = ImTrunc(TreeLinesSize * scale_factor);
|
||||||
TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor);
|
TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor);
|
||||||
DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor);
|
DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor);
|
||||||
DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor);
|
DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor);
|
||||||
DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor);
|
DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor);
|
||||||
ColorMarkerSize = ImTrunc(ColorMarkerSize * scale_factor);
|
ColorMarkerSize = ImTrunc(ColorMarkerSize * scale_factor);
|
||||||
|
SeparatorSize = ImTrunc(SeparatorSize * scale_factor);
|
||||||
|
SeparatorTextBorderSize = ImTrunc(SeparatorTextBorderSize * scale_factor);
|
||||||
SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
|
SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
|
||||||
DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
|
DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
|
||||||
DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
|
DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
|
||||||
@ -3309,7 +3337,6 @@ ImGuiListClipper::~ImGuiListClipper()
|
|||||||
|
|
||||||
void ImGuiListClipper::Begin(int items_count, float items_height)
|
void ImGuiListClipper::Begin(int items_count, float items_height)
|
||||||
{
|
{
|
||||||
if (Ctx == NULL)
|
|
||||||
Ctx = ImGui::GetCurrentContext();
|
Ctx = ImGui::GetCurrentContext();
|
||||||
|
|
||||||
ImGuiContext& g = *Ctx;
|
ImGuiContext& g = *Ctx;
|
||||||
@ -3356,6 +3383,7 @@ void ImGuiListClipper::End()
|
|||||||
}
|
}
|
||||||
TempData = NULL;
|
TempData = NULL;
|
||||||
}
|
}
|
||||||
|
DisplayStart = DisplayEnd = ItemsCount; // Clear this so code which may be reused past last Step() won't trip on a non-empty range.
|
||||||
ItemsCount = -1;
|
ItemsCount = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3560,7 +3588,7 @@ bool ImGuiListClipper::Step()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic helper, equivalent to old ImGui::CalcListClipping() but statelesss
|
// Generic helper, equivalent to old ImGui::CalcListClipping() but stateless
|
||||||
void ImGui::CalcClipRectVisibleItemsY(const ImRect& clip_rect, const ImVec2& pos, float items_height, int* out_visible_start, int* out_visible_end)
|
void ImGui::CalcClipRectVisibleItemsY(const ImRect& clip_rect, const ImVec2& pos, float items_height, int* out_visible_start, int* out_visible_end)
|
||||||
{
|
{
|
||||||
*out_visible_start = ImMax((int)((clip_rect.Min.y - pos.y) / items_height), 0);
|
*out_visible_start = ImMax((int)((clip_rect.Min.y - pos.y) / items_height), 0);
|
||||||
@ -3694,6 +3722,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
|
|||||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
||||||
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorSize)}, // ImGuiStyleVar_SeparatorSize
|
||||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
|
||||||
@ -4270,6 +4299,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
NavWindow = NULL;
|
NavWindow = NULL;
|
||||||
NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
|
NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
|
||||||
NavLayer = ImGuiNavLayer_Main;
|
NavLayer = ImGuiNavLayer_Main;
|
||||||
|
NavIdItemFlags = ImGuiItemFlags_None;
|
||||||
|
NavOpenContextMenuItemId = NavOpenContextMenuWindowId = 0;
|
||||||
NavNextActivateId = 0;
|
NavNextActivateId = 0;
|
||||||
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
||||||
NavHighlightActivatedId = 0;
|
NavHighlightActivatedId = 0;
|
||||||
@ -4339,6 +4370,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
MouseStationaryTimer = 0.0f;
|
MouseStationaryTimer = 0.0f;
|
||||||
|
|
||||||
InputTextPasswordFontBackupFlags = ImFontFlags_None;
|
InputTextPasswordFontBackupFlags = ImFontFlags_None;
|
||||||
|
InputTextReactivateId = 0;
|
||||||
TempInputId = 0;
|
TempInputId = 0;
|
||||||
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
|
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
|
||||||
BeginMenuDepth = BeginComboDepth = 0;
|
BeginMenuDepth = BeginComboDepth = 0;
|
||||||
@ -4368,6 +4400,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
SettingsLoaded = false;
|
SettingsLoaded = false;
|
||||||
SettingsDirtyTimer = 0.0f;
|
SettingsDirtyTimer = 0.0f;
|
||||||
HookIdNext = 0;
|
HookIdNext = 0;
|
||||||
|
DemoMarkerCallback = NULL;
|
||||||
|
|
||||||
memset(LocalizationTable, 0, sizeof(LocalizationTable));
|
memset(LocalizationTable, 0, sizeof(LocalizationTable));
|
||||||
|
|
||||||
@ -4705,11 +4738,12 @@ void ImGui::GcCompactTransientMiscBuffers()
|
|||||||
// Not freed:
|
// Not freed:
|
||||||
// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data)
|
// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data)
|
||||||
// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
|
// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
|
||||||
|
// FIXME: Consider exposing of elaborating GC policy, e.g. being able to trim excessive ImDrawList gaps. (#9303)
|
||||||
void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
|
void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
|
||||||
{
|
{
|
||||||
window->MemoryCompacted = true;
|
window->MemoryCompacted = true;
|
||||||
window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
|
window->MemoryDrawListIdxCapacity = ImMin((int)(window->DrawList->IdxBuffer.Size * 1.05f), window->DrawList->IdxBuffer.Capacity);
|
||||||
window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
|
window->MemoryDrawListVtxCapacity = ImMin((int)(window->DrawList->VtxBuffer.Size * 1.05f), window->DrawList->VtxBuffer.Capacity);
|
||||||
window->IDStack.clear();
|
window->IDStack.clear();
|
||||||
window->DrawList->_ClearFreeMemory();
|
window->DrawList->_ClearFreeMemory();
|
||||||
window->DC.ChildWindows.clear();
|
window->DC.ChildWindows.clear();
|
||||||
@ -5171,6 +5205,13 @@ void ImGui::MemFree(void* ptr)
|
|||||||
return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
|
return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGui::DemoMarker(const char* file, int line, const char* section)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.DemoMarkerCallback != NULL)
|
||||||
|
g.DemoMarkerCallback(file, line, section);
|
||||||
|
}
|
||||||
|
|
||||||
// We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames"
|
// We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames"
|
||||||
void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size)
|
void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size)
|
||||||
{
|
{
|
||||||
@ -5274,12 +5315,12 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Our ImDrawList system requires that there is always a command
|
// Our ImDrawList system requires that there is always a command
|
||||||
if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
|
if (viewport->BgFgDrawListsLastTimeActive[drawlist_no] != (float)g.Time)
|
||||||
{
|
{
|
||||||
draw_list->_ResetForNewFrame();
|
draw_list->_ResetForNewFrame();
|
||||||
draw_list->PushTexture(g.IO.Fonts->TexRef);
|
draw_list->PushTexture(g.IO.Fonts->TexRef);
|
||||||
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
|
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
|
||||||
viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
|
viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time;
|
||||||
}
|
}
|
||||||
return draw_list;
|
return draw_list;
|
||||||
}
|
}
|
||||||
@ -5718,7 +5759,7 @@ void ImGui::NewFrame()
|
|||||||
// As a result, custom widget using ButtonBehavior() _without_ ItemAdd() need to call KeepAliveID() themselves.
|
// As a result, custom widget using ButtonBehavior() _without_ ItemAdd() need to call KeepAliveID() themselves.
|
||||||
if (g.ActiveId != 0 && g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId)
|
if (g.ActiveId != 0 && g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId)
|
||||||
{
|
{
|
||||||
IMGUI_DEBUG_LOG_ACTIVEID("NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
|
IMGUI_DEBUG_LOG_ACTIVEID("NewFrame(): ClearActiveID() 0x%08X because it isn't marked alive anymore!\n", g.ActiveId);
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5732,6 +5773,8 @@ void ImGui::NewFrame()
|
|||||||
g.ActiveIdIsJustActivated = false;
|
g.ActiveIdIsJustActivated = false;
|
||||||
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
|
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
|
||||||
g.TempInputId = 0;
|
g.TempInputId = 0;
|
||||||
|
if (g.InputTextReactivateId != 0 && g.InputTextReactivateId != g.DeactivatedItemData.ID)
|
||||||
|
g.InputTextReactivateId = 0;
|
||||||
if (g.ActiveId == 0)
|
if (g.ActiveId == 0)
|
||||||
{
|
{
|
||||||
g.ActiveIdUsingNavDirMask = 0x00;
|
g.ActiveIdUsingNavDirMask = 0x00;
|
||||||
@ -5818,7 +5861,8 @@ void ImGui::NewFrame()
|
|||||||
|
|
||||||
// Mark all windows as not visible and compact unused memory.
|
// Mark all windows as not visible and compact unused memory.
|
||||||
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
|
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
|
||||||
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
|
const bool gc_all = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f);
|
||||||
|
const float memory_compact_start_time = gc_all ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
|
||||||
for (ImGuiWindow* window : g.Windows)
|
for (ImGuiWindow* window : g.Windows)
|
||||||
{
|
{
|
||||||
window->WasActive = window->Active;
|
window->WasActive = window->Active;
|
||||||
@ -5828,7 +5872,7 @@ void ImGui::NewFrame()
|
|||||||
window->BeginCount = 0;
|
window->BeginCount = 0;
|
||||||
|
|
||||||
// Garbage collect transient buffers of recently unused windows
|
// Garbage collect transient buffers of recently unused windows
|
||||||
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
|
if ((!window->WasActive || gc_all) && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
|
||||||
GcCompactTransientWindowBuffers(window);
|
GcCompactTransientWindowBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6070,7 +6114,7 @@ static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32
|
|||||||
draw_list->ChannelsMerge();
|
draw_list->ChannelsMerge();
|
||||||
if (draw_list->CmdBuffer.Size == 0)
|
if (draw_list->CmdBuffer.Size == 0)
|
||||||
draw_list->AddDrawCmd();
|
draw_list->AddDrawCmd();
|
||||||
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to stricty ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that)
|
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to strictly ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that)
|
||||||
ImDrawCmd cmd = draw_list->CmdBuffer.back();
|
ImDrawCmd cmd = draw_list->CmdBuffer.back();
|
||||||
IM_ASSERT(cmd.ElemCount == 0);
|
IM_ASSERT(cmd.ElemCount == 0);
|
||||||
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
|
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
|
||||||
@ -6203,10 +6247,14 @@ void ImGui::EndFrame()
|
|||||||
}
|
}
|
||||||
g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0;
|
g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0;
|
||||||
|
|
||||||
// Hide implicit/fallback "Debug" window if it hasn't been used
|
// Hide and unfocus implicit/fallback "Debug" window if it hasn't been used
|
||||||
g.WithinFrameScopeWithImplicitWindow = false;
|
g.WithinFrameScopeWithImplicitWindow = false;
|
||||||
if (g.CurrentWindow && g.CurrentWindow->IsFallbackWindow && g.CurrentWindow->WriteAccessed == false)
|
if (g.CurrentWindow && g.CurrentWindow->IsFallbackWindow && g.CurrentWindow->WriteAccessed == false)
|
||||||
|
{
|
||||||
g.CurrentWindow->Active = false;
|
g.CurrentWindow->Active = false;
|
||||||
|
if (g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow)
|
||||||
|
FocusWindow(NULL);
|
||||||
|
}
|
||||||
End();
|
End();
|
||||||
|
|
||||||
// Update navigation: Ctrl+Tab, wrap-around requests
|
// Update navigation: Ctrl+Tab, wrap-around requests
|
||||||
@ -6301,7 +6349,7 @@ void ImGui::Render()
|
|||||||
for (ImGuiViewportP* viewport : g.Viewports)
|
for (ImGuiViewportP* viewport : g.Viewports)
|
||||||
{
|
{
|
||||||
InitViewportDrawData(viewport);
|
InitViewportDrawData(viewport);
|
||||||
if (viewport->BgFgDrawLists[0] != NULL)
|
if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastTimeActive[0] == (float)g.Time)
|
||||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
|
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6333,7 +6381,7 @@ void ImGui::Render()
|
|||||||
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
|
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
|
||||||
|
|
||||||
// Add foreground ImDrawList (for each active viewport)
|
// Add foreground ImDrawList (for each active viewport)
|
||||||
if (viewport->BgFgDrawLists[1] != NULL)
|
if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastTimeActive[1] == (float)g.Time)
|
||||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
|
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
|
||||||
|
|
||||||
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
|
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
|
||||||
@ -10660,11 +10708,12 @@ static void UpdateAliasKey(ImGuiKey key, bool v, float analog_value)
|
|||||||
// [Internal] Do not use directly
|
// [Internal] Do not use directly
|
||||||
static ImGuiKeyChord GetMergedModsFromKeys()
|
static ImGuiKeyChord GetMergedModsFromKeys()
|
||||||
{
|
{
|
||||||
|
// Bypass IsKeyDown() for the unlikely case where user used a ImGuiInputFlags_LockXXXX on those.
|
||||||
ImGuiKeyChord mods = 0;
|
ImGuiKeyChord mods = 0;
|
||||||
if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; }
|
if (ImGui::GetKeyData(ImGuiMod_Ctrl)->Down) { mods |= ImGuiMod_Ctrl; }
|
||||||
if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; }
|
if (ImGui::GetKeyData(ImGuiMod_Shift)->Down) { mods |= ImGuiMod_Shift; }
|
||||||
if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; }
|
if (ImGui::GetKeyData(ImGuiMod_Alt)->Down) { mods |= ImGuiMod_Alt; }
|
||||||
if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; }
|
if (ImGui::GetKeyData(ImGuiMod_Super)->Down) { mods |= ImGuiMod_Super; }
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11747,6 +11796,8 @@ bool ImGui::ErrorLog(const char* msg)
|
|||||||
return g.IO.ConfigErrorRecoveryEnableAssert;
|
return g.IO.ConfigErrorRecoveryEnableAssert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Display an error tooltip when same ID as HoveredId was submitted multiple times.
|
||||||
|
// See code in ItemHoverable() for an explanation of why we associate this error to HoveredId + code drawing of rectangles over individual items instances.
|
||||||
void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||||
{
|
{
|
||||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
@ -12930,16 +12981,16 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|||||||
// - Each popups may contain child windows, which is why we compare ->RootWindowDockTree!
|
// - Each popups may contain child windows, which is why we compare ->RootWindowDockTree!
|
||||||
// Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
|
// Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
|
||||||
// We step through every popup from bottom to top to validate their position relative to reference window.
|
// We step through every popup from bottom to top to validate their position relative to reference window.
|
||||||
bool ref_window_is_descendent_of_popup = false;
|
bool ref_window_is_descendant_of_popup = false;
|
||||||
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
|
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
|
||||||
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
|
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
|
||||||
//if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree) // FIXME-MERGE
|
//if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree) // FIXME-MERGE
|
||||||
if (IsWindowWithinBeginStackOf(ref_window, popup_window))
|
if (IsWindowWithinBeginStackOf(ref_window, popup_window))
|
||||||
{
|
{
|
||||||
ref_window_is_descendent_of_popup = true;
|
ref_window_is_descendant_of_popup = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!ref_window_is_descendent_of_popup)
|
if (!ref_window_is_descendant_of_popup)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13143,14 +13194,37 @@ ImGuiMouseButton ImGui::GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags)
|
|||||||
return ImGuiMouseButton_Right; // Default == 1
|
return ImGuiMouseButton_Right; // Default == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
||||||
|
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||||
|
return true;
|
||||||
|
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
||||||
|
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||||
|
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
|
||||||
|
return true;
|
||||||
|
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
|
||||||
|
if (IsWindowChildOf(g.NavWindow, g.CurrentWindow, false, false)) // This enable ordering to be used to disambiguate item vs window (#8803)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to open a popup if mouse button is released over the item
|
// Helper to open a popup if mouse button is released over the item
|
||||||
// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
|
// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
|
||||||
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
|
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
|
||||||
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
||||||
{
|
{
|
||||||
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
|
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
|
||||||
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
|
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
|
||||||
@ -13182,8 +13256,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag
|
|||||||
return false;
|
return false;
|
||||||
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItem ID. Using LastItem ID as a Popup ID won't conflict!
|
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItem ID. Using LastItem ID as a Popup ID won't conflict!
|
||||||
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
|
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
|
||||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
|
||||||
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
||||||
OpenPopupEx(id, popup_flags);
|
OpenPopupEx(id, popup_flags);
|
||||||
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
||||||
}
|
}
|
||||||
@ -13195,9 +13268,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl
|
|||||||
if (!str_id)
|
if (!str_id)
|
||||||
str_id = "window_context";
|
str_id = "window_context";
|
||||||
ImGuiID id = window->GetID(str_id);
|
ImGuiID id = window->GetID(str_id);
|
||||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
if (IsPopupOpenRequestForWindow(popup_flags))
|
||||||
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
|
||||||
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
|
|
||||||
OpenPopupEx(id, popup_flags);
|
OpenPopupEx(id, popup_flags);
|
||||||
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
||||||
}
|
}
|
||||||
@ -13748,6 +13819,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
|||||||
window->NavLastIds[nav_layer] = id;
|
window->NavLastIds[nav_layer] = id;
|
||||||
if (g.LastItemData.ID == id)
|
if (g.LastItemData.ID == id)
|
||||||
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||||
|
g.NavIdItemFlags = (g.LastItemData.ID == id) ? g.LastItemData.ItemFlags : ImGuiItemFlags_None;
|
||||||
if (id == g.ActiveIdIsAlive)
|
if (id == g.ActiveIdIsAlive)
|
||||||
g.NavIdIsAlive = true;
|
g.NavIdIsAlive = true;
|
||||||
|
|
||||||
@ -14017,6 +14089,7 @@ static void ImGui::NavProcessItem()
|
|||||||
SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
|
SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
|
||||||
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
||||||
g.NavIdIsAlive = true;
|
g.NavIdIsAlive = true;
|
||||||
|
g.NavIdItemFlags = item_flags;
|
||||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
|
if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
|
||||||
{
|
{
|
||||||
IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
|
IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
|
||||||
@ -14407,6 +14480,7 @@ static void ImGui::NavUpdate()
|
|||||||
|
|
||||||
// Process NavCancel input (to close a popup, get back to parent, clear focus)
|
// Process NavCancel input (to close a popup, get back to parent, clear focus)
|
||||||
NavUpdateCancelRequest();
|
NavUpdateCancelRequest();
|
||||||
|
NavUpdateContextMenuRequest();
|
||||||
|
|
||||||
// Process manual activation request
|
// Process manual activation request
|
||||||
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
|
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
|
||||||
@ -14415,21 +14489,25 @@ static void ImGui::NavUpdate()
|
|||||||
{
|
{
|
||||||
const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
|
const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
|
||||||
const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
|
const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
|
||||||
const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_NoOwner) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_NoOwner));
|
const bool input_pressed_keyboard = nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) || IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner));
|
||||||
const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) || IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, 0, ImGuiKeyOwner_NoOwner)));
|
bool input_pressed_gamepad = false;
|
||||||
|
if (activate_down && nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner) && (g.NavIdItemFlags & ImGuiItemFlags_Inputable)) // requires ImGuiItemFlags_Inputable to avoid retriggering regular buttons.
|
||||||
|
if (GetKeyData(ImGuiKey_NavGamepadActivate)->DownDurationPrev < NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY && GetKeyData(ImGuiKey_NavGamepadActivate)->DownDuration >= NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY)
|
||||||
|
input_pressed_gamepad = true;
|
||||||
|
|
||||||
if (g.ActiveId == 0 && activate_pressed)
|
if (g.ActiveId == 0 && activate_pressed)
|
||||||
{
|
{
|
||||||
g.NavActivateId = g.NavId;
|
g.NavActivateId = g.NavId;
|
||||||
g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
|
g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
|
||||||
}
|
}
|
||||||
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
|
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (input_pressed_keyboard || input_pressed_gamepad))
|
||||||
{
|
{
|
||||||
g.NavActivateId = g.NavId;
|
g.NavActivateId = g.NavId;
|
||||||
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
|
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
|
||||||
}
|
}
|
||||||
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down))
|
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_pressed_keyboard || input_pressed_gamepad)) // FIXME-NAV: Unsure why input_pressed_xxx (migrated from input_down which was already dubious)
|
||||||
g.NavActivateDownId = g.NavId;
|
g.NavActivateDownId = g.NavId;
|
||||||
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed))
|
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed_keyboard || input_pressed_gamepad))
|
||||||
{
|
{
|
||||||
g.NavActivatePressedId = g.NavId;
|
g.NavActivatePressedId = g.NavId;
|
||||||
NavHighlightActivated(g.NavId);
|
NavHighlightActivated(g.NavId);
|
||||||
@ -14891,6 +14969,31 @@ static void ImGui::NavUpdateCancelRequest()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ImGui::NavUpdateContextMenuRequest()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
|
||||||
|
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||||
|
const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||||
|
if ((!nav_keyboard_active && !nav_gamepad_active) || g.NavWindow == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool request = false;
|
||||||
|
request |= nav_keyboard_active && (IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner) || (IsKeyPressed(ImGuiKey_F10, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner) && g.IO.KeyMods == ImGuiMod_Shift));
|
||||||
|
request |= nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadContextMenu, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner);
|
||||||
|
if (!request)
|
||||||
|
return;
|
||||||
|
g.NavOpenContextMenuItemId = g.NavId;
|
||||||
|
g.NavOpenContextMenuWindowId = g.NavWindow->ID;
|
||||||
|
|
||||||
|
// Allow triggering for Begin()..BeginPopupContextItem(). A possible alternative would be to use g.NavLayer == ImGuiNavLayer_Menu.
|
||||||
|
if (g.NavId == g.NavWindow->GetID("#CLOSE") || g.NavId == g.NavWindow->GetID("#COLLAPSE"))
|
||||||
|
g.NavOpenContextMenuItemId = g.NavWindow->MoveId;
|
||||||
|
|
||||||
|
g.NavInputSource = ImGuiInputSource_Keyboard;
|
||||||
|
SetNavCursorVisibleAfterMove();
|
||||||
|
}
|
||||||
|
|
||||||
// Handle PageUp/PageDown/Home/End keys
|
// Handle PageUp/PageDown/Home/End keys
|
||||||
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
|
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
|
||||||
// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
|
// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
|
||||||
@ -15447,7 +15550,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
|
|||||||
|
|
||||||
// Magic fallback to handle items with no assigned ID, e.g. Text(), Image()
|
// Magic fallback to handle items with no assigned ID, e.g. Text(), Image()
|
||||||
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
|
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
|
||||||
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZINGG OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
|
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
|
||||||
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
|
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
|
||||||
// Rely on keeping other window->LastItemXXX fields intact.
|
// Rely on keeping other window->LastItemXXX fields intact.
|
||||||
source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
|
source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
|
||||||
@ -15561,14 +15664,14 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
|
|||||||
// Store in heap
|
// Store in heap
|
||||||
g.DragDropPayloadBufHeap.resize((int)data_size);
|
g.DragDropPayloadBufHeap.resize((int)data_size);
|
||||||
payload.Data = g.DragDropPayloadBufHeap.Data;
|
payload.Data = g.DragDropPayloadBufHeap.Data;
|
||||||
memcpy(payload.Data, data, data_size);
|
memcpy(payload.Data, data, (size_t)(int)data_size);
|
||||||
}
|
}
|
||||||
else if (data_size > 0)
|
else if (data_size > 0)
|
||||||
{
|
{
|
||||||
// Store locally
|
// Store locally
|
||||||
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
|
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
|
||||||
payload.Data = g.DragDropPayloadBufLocal;
|
payload.Data = g.DragDropPayloadBufLocal;
|
||||||
memcpy(payload.Data, data, data_size);
|
memcpy(payload.Data, data, (size_t)(int)data_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -16438,6 +16541,12 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count)
|
|||||||
// - DestroyPlatformWindows()
|
// - DestroyPlatformWindows()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char* ImGuiViewport::GetDebugName() const
|
||||||
|
{
|
||||||
|
const ImGuiViewportP* viewport = (const ImGuiViewportP*)this;
|
||||||
|
return viewport->Window ? viewport->Window->Name : "n/a";
|
||||||
|
}
|
||||||
|
|
||||||
void ImGuiPlatformIO::ClearPlatformHandlers()
|
void ImGuiPlatformIO::ClearPlatformHandlers()
|
||||||
{
|
{
|
||||||
Platform_GetClipboardTextFn = NULL;
|
Platform_GetClipboardTextFn = NULL;
|
||||||
@ -16648,7 +16757,7 @@ void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the backend doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves.
|
// If the backend doesn't support ImGuiBackendFlags_HasMouseHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs for it, we do a search ourselves.
|
||||||
// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||||
// B) It requires Platform_GetWindowFocus to be implemented by backend.
|
// B) It requires Platform_GetWindowFocus to be implemented by backend.
|
||||||
ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(const ImVec2& mouse_platform_pos)
|
ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(const ImVec2& mouse_platform_pos)
|
||||||
@ -16658,6 +16767,7 @@ ImGuiViewportP* ImGui::FindHoveredViewportFromPlatformWindowStack(const ImVec2&
|
|||||||
for (ImGuiViewportP* viewport : g.Viewports)
|
for (ImGuiViewportP* viewport : g.Viewports)
|
||||||
if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) && viewport->GetMainRect().Contains(mouse_platform_pos))
|
if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) && viewport->GetMainRect().Contains(mouse_platform_pos))
|
||||||
if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
|
if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
|
||||||
|
if (viewport->PlatformWindowCreated)
|
||||||
best_candidate = viewport;
|
best_candidate = viewport;
|
||||||
return best_candidate;
|
return best_candidate;
|
||||||
}
|
}
|
||||||
@ -16752,6 +16862,8 @@ static void ImGui::UpdateViewportsNewFrame()
|
|||||||
}
|
}
|
||||||
AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size, ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
|
AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size, ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
|
||||||
|
|
||||||
|
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
|
||||||
|
|
||||||
g.CurrentDpiScale = 0.0f;
|
g.CurrentDpiScale = 0.0f;
|
||||||
g.CurrentViewport = NULL;
|
g.CurrentViewport = NULL;
|
||||||
g.MouseViewport = NULL;
|
g.MouseViewport = NULL;
|
||||||
@ -16802,6 +16914,14 @@ static void ImGui::UpdateViewportsNewFrame()
|
|||||||
}
|
}
|
||||||
viewport->UpdateWorkRect();
|
viewport->UpdateWorkRect();
|
||||||
|
|
||||||
|
// Garbage collect transient buffers of recently BG/FG drawlists
|
||||||
|
for (int dl_n = 0; dl_n < IM_COUNTOF(viewport->BgFgDrawLists); dl_n++)
|
||||||
|
if (viewport->BgFgDrawListsLastTimeActive[dl_n] < memory_compact_start_time && viewport->BgFgDrawLists[dl_n] != NULL)
|
||||||
|
{
|
||||||
|
IM_DELETE(viewport->BgFgDrawLists[dl_n]);
|
||||||
|
viewport->BgFgDrawLists[dl_n] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset alpha every frame. Users of transparency (docking) needs to request a lower alpha back.
|
// Reset alpha every frame. Users of transparency (docking) needs to request a lower alpha back.
|
||||||
viewport->Alpha = 1.0f;
|
viewport->Alpha = 1.0f;
|
||||||
|
|
||||||
@ -16880,7 +17000,7 @@ static void ImGui::UpdateViewportsNewFrame()
|
|||||||
// If the backend doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
|
// If the backend doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
|
||||||
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
||||||
// B) won't take account of how the backend apply parent<>child relationship to secondary viewports, which affects their Z order.
|
// B) won't take account of how the backend apply parent<>child relationship to secondary viewports, which affects their Z order.
|
||||||
// C) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
|
// C) uses LastFocusedStampCount as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
|
||||||
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
|
viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
|
||||||
}
|
}
|
||||||
if (viewport_hovered != NULL)
|
if (viewport_hovered != NULL)
|
||||||
@ -22605,6 +22725,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|||||||
{
|
{
|
||||||
ImGuiDebugAllocInfo* info = &g.DebugAllocInfo;
|
ImGuiDebugAllocInfo* info = &g.DebugAllocInfo;
|
||||||
Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
|
Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
|
||||||
|
Text("Releasing selected unused buffers after: %.2f secs", g.IO.ConfigMemoryCompactTimer);
|
||||||
if (SmallButton("GC now")) { g.GcCompactAll = true; }
|
if (SmallButton("GC now")) { g.GcCompactAll = true; }
|
||||||
Text("Recent frames with allocations:");
|
Text("Recent frames with allocations:");
|
||||||
int buf_size = IM_COUNTOF(info->LastEntriesBuf);
|
int buf_size = IM_COUNTOF(info->LastEntriesBuf);
|
||||||
@ -23276,7 +23397,7 @@ void ImGui::DebugNodeFont(ImFont* font)
|
|||||||
src_n, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
|
src_n, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugNodeFontGlyphesForSrcMask(font, baked, ~0);
|
DebugNodeFontGlyphsForSrcMask(font, baked, ~0);
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
PopID();
|
PopID();
|
||||||
@ -23285,7 +23406,7 @@ void ImGui::DebugNodeFont(ImFont* font)
|
|||||||
Unindent();
|
Unindent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask)
|
void ImGui::DebugNodeFontGlyphsForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask)
|
||||||
{
|
{
|
||||||
ImDrawList* draw_list = GetWindowDrawList();
|
ImDrawList* draw_list = GetWindowDrawList();
|
||||||
const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
|
const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
|
||||||
@ -24089,7 +24210,7 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
|
|||||||
void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*, const ImDrawList*, const char*) {}
|
void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*, const ImDrawList*, const char*) {}
|
||||||
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
|
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
|
||||||
void ImGui::DebugNodeFont(ImFont*) {}
|
void ImGui::DebugNodeFont(ImFont*) {}
|
||||||
void ImGui::DebugNodeFontGlyphesForSrcMask(ImFont*, ImFontBaked*, int) {}
|
void ImGui::DebugNodeFontGlyphsForSrcMask(ImFont*, ImFontBaked*, int) {}
|
||||||
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
|
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
|
||||||
void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
|
void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
|
||||||
void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
|
void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (headers)
|
// (headers)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
@ -20,7 +20,7 @@
|
|||||||
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
|
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
|
||||||
// - Issues & support ........... https://github.com/ocornut/imgui/issues
|
// - Issues & support ........... https://github.com/ocornut/imgui/issues
|
||||||
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
|
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
|
||||||
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
|
// - Web version of the Demo .... https://pthom.github.io/imgui_explorer (w/ source code browser)
|
||||||
|
|
||||||
// For FIRST-TIME users having issues compiling/linking/running:
|
// For FIRST-TIME users having issues compiling/linking/running:
|
||||||
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
|
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
|
||||||
@ -29,8 +29,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.6"
|
#define IMGUI_VERSION "1.92.7"
|
||||||
#define IMGUI_VERSION_NUM 19261
|
#define IMGUI_VERSION_NUM 19270
|
||||||
#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.
|
||||||
@ -345,7 +345,9 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
|
|||||||
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
|
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define this if you need 0 to be a valid ImTextureID for your backend.
|
// Define this if you need to change the invalid value for your backend.
|
||||||
|
// - If your backend is using ImTextureID to store an index/offset and you need 0 to be valid, You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
|
||||||
|
// - From 2026/03/12 to 2026/03/19 we experimented with changing to default to -1, but I worried it would cause too many issues in third-party code so it was reverted.
|
||||||
#ifndef ImTextureID_Invalid
|
#ifndef ImTextureID_Invalid
|
||||||
#define ImTextureID_Invalid ((ImTextureID)0)
|
#define ImTextureID_Invalid ((ImTextureID)0)
|
||||||
#endif
|
#endif
|
||||||
@ -764,6 +766,7 @@ namespace ImGui
|
|||||||
IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
|
IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
|
||||||
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
|
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
|
||||||
IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id).
|
IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id).
|
||||||
|
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); // retrieve tree node open/close state.
|
||||||
|
|
||||||
// Widgets: Selectables
|
// Widgets: Selectables
|
||||||
// - A selectable highlights when hovered, and can display another color when selected.
|
// - A selectable highlights when hovered, and can display another color when selected.
|
||||||
@ -919,7 +922,7 @@ namespace ImGui
|
|||||||
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
|
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
|
||||||
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
|
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
|
||||||
// some advanced use cases (e.g. adding custom widgets in header row).
|
// some advanced use cases (e.g. adding custom widgets in header row).
|
||||||
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled.
|
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
|
||||||
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
|
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
|
||||||
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
|
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
|
||||||
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
|
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
|
||||||
@ -1034,7 +1037,7 @@ namespace ImGui
|
|||||||
IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
|
IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
|
||||||
|
|
||||||
// Overlapping mode
|
// Overlapping mode
|
||||||
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
|
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Typically useful with InvisibleButton(), Selectable(), TreeNode() covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
|
||||||
|
|
||||||
// Item/Widgets Utilities and Query Functions
|
// Item/Widgets Utilities and Query Functions
|
||||||
// - Most of the functions are referring to the previous Item that has been submitted.
|
// - Most of the functions are referring to the previous Item that has been submitted.
|
||||||
@ -1305,7 +1308,7 @@ enum ImGuiInputTextFlags_
|
|||||||
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
|
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
|
||||||
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
|
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
|
||||||
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
|
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
|
||||||
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
|
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way.
|
||||||
|
|
||||||
// Other options
|
// Other options
|
||||||
ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
|
ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
|
||||||
@ -1347,13 +1350,13 @@ enum ImGuiTreeNodeFlags_
|
|||||||
ImGuiTreeNodeFlags_None = 0,
|
ImGuiTreeNodeFlags_None = 0,
|
||||||
ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
|
ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
|
||||||
ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader)
|
ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader)
|
||||||
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
|
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
|
||||||
ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
|
ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
|
||||||
ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
|
ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
|
||||||
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
|
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
|
||||||
ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Open on double-click instead of simple click (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Open on double-click instead of simple click (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
||||||
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
||||||
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
|
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). Note: will always open a tree/id scope and return true. If you never use that scope, add ImGuiTreeNodeFlags_NoTreePushOnOpen.
|
||||||
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
|
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
|
||||||
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
|
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
|
||||||
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
|
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
|
||||||
@ -1407,7 +1410,7 @@ enum ImGuiSelectableFlags_
|
|||||||
ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column)
|
ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column)
|
||||||
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
|
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
|
||||||
ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text
|
ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text
|
||||||
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one
|
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
|
||||||
ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered
|
ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered
|
||||||
ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into, unless Ctrl is held. Automatic when in a BeginMultiSelect() block.
|
ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into, unless Ctrl is held. Automatic when in a BeginMultiSelect() block.
|
||||||
|
|
||||||
@ -1683,10 +1686,10 @@ enum ImGuiKey : int
|
|||||||
// // XBOX | SWITCH | PLAYSTA. | -> ACTION
|
// // XBOX | SWITCH | PLAYSTA. | -> ACTION
|
||||||
ImGuiKey_GamepadStart, // Menu | + | Options |
|
ImGuiKey_GamepadStart, // Menu | + | Options |
|
||||||
ImGuiKey_GamepadBack, // View | - | Share |
|
ImGuiKey_GamepadBack, // View | - | Share |
|
||||||
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
|
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Toggle Menu. Hold for Windowing mode (Focus/Move/Resize windows)
|
||||||
ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / Close / Exit
|
ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / Close / Exit
|
||||||
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Text Input / On-screen Keyboard
|
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Open Context Menu
|
||||||
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle / Tweak
|
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle. Hold for 0.60f to Activate in Text Input mode (e.g. wired to an on-screen keyboard).
|
||||||
ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||||
ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||||
ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||||
@ -1768,6 +1771,7 @@ enum ImGuiInputFlags_
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Configuration flags stored in io.ConfigFlags. Set by user/application.
|
// Configuration flags stored in io.ConfigFlags. Set by user/application.
|
||||||
|
// Note that nowadays most of our configuration options are in other ImGuiIO fields, e.g. io.ConfigWindowsMoveFromTitleBarOnly.
|
||||||
enum ImGuiConfigFlags_
|
enum ImGuiConfigFlags_
|
||||||
{
|
{
|
||||||
ImGuiConfigFlags_None = 0,
|
ImGuiConfigFlags_None = 0,
|
||||||
@ -1784,10 +1788,9 @@ enum ImGuiConfigFlags_
|
|||||||
// When using viewports it is recommended that your default value for ImGuiCol_WindowBg is opaque (Alpha=1.0) so transition to a viewport won't be noticeable.
|
// When using viewports it is recommended that your default value for ImGuiCol_WindowBg is opaque (Alpha=1.0) so transition to a viewport won't be noticeable.
|
||||||
ImGuiConfigFlags_ViewportsEnable = 1 << 10, // Viewport enable flags (require both ImGuiBackendFlags_PlatformHasViewports + ImGuiBackendFlags_RendererHasViewports set by the respective backends)
|
ImGuiConfigFlags_ViewportsEnable = 1 << 10, // Viewport enable flags (require both ImGuiBackendFlags_PlatformHasViewports + ImGuiBackendFlags_RendererHasViewports set by the respective backends)
|
||||||
|
|
||||||
// User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
|
// [Unused] User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
|
||||||
ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
|
ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
|
||||||
ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse.
|
ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse.
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos
|
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos
|
||||||
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard
|
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard
|
||||||
@ -1936,6 +1939,7 @@ enum ImGuiStyleVar_
|
|||||||
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
||||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||||
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
||||||
|
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
|
||||||
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
|
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
|
||||||
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
|
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
|
||||||
ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
|
ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
|
||||||
@ -1952,6 +1956,7 @@ enum ImGuiButtonFlags_
|
|||||||
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
|
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
|
||||||
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
|
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
|
||||||
ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
|
ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
|
||||||
|
ImGuiButtonFlags_AllowOverlap = 1 << 12, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
|
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
|
||||||
@ -2111,11 +2116,11 @@ enum ImGuiTableFlags_
|
|||||||
// Features
|
// Features
|
||||||
ImGuiTableFlags_None = 0,
|
ImGuiTableFlags_None = 0,
|
||||||
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
|
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
|
||||||
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
|
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row. (Need calling TableSetupColumn() + TableHeadersRow() to display headers, or using ImGuiTableFlags_ContextMenuInBody to access context-menu without headers).
|
||||||
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
|
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
|
||||||
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
|
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
|
||||||
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file.
|
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file.
|
||||||
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
|
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will also display table context menu. By default it is available in TableHeadersRow().
|
||||||
// Decorations
|
// Decorations
|
||||||
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
|
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
|
||||||
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
|
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
|
||||||
@ -2416,6 +2421,7 @@ struct ImGuiStyle
|
|||||||
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||||
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
||||||
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||||
|
float SeparatorSize; // Thickness of border in Separator()
|
||||||
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
||||||
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||||
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
||||||
@ -2442,7 +2448,7 @@ struct ImGuiStyle
|
|||||||
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
||||||
|
|
||||||
// [Internal]
|
// [Internal]
|
||||||
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes().
|
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes(). PLEASE DO NOT USE THIS FOR NOW.
|
||||||
float _NextFrameFontSizeBase; // FIXME: Temporary hack until we finish remaining work.
|
float _NextFrameFontSizeBase; // FIXME: Temporary hack until we finish remaining work.
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
@ -2532,7 +2538,7 @@ struct ImGuiIO
|
|||||||
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
||||||
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
||||||
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
||||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
|
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
|
||||||
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
||||||
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
||||||
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
|
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
|
||||||
@ -2982,15 +2988,16 @@ enum ImGuiListClipperFlags_
|
|||||||
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
|
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
|
||||||
struct ImGuiListClipper
|
struct ImGuiListClipper
|
||||||
{
|
{
|
||||||
ImGuiContext* Ctx; // Parent UI context
|
|
||||||
int DisplayStart; // First item to display, updated by each call to Step()
|
int DisplayStart; // First item to display, updated by each call to Step()
|
||||||
int DisplayEnd; // End of items to display (exclusive)
|
int DisplayEnd; // End of items to display (exclusive)
|
||||||
|
int UserIndex; // Helper storage for user convenience/code. Optional, and otherwise unused if you don't use it.
|
||||||
int ItemsCount; // [Internal] Number of items
|
int ItemsCount; // [Internal] Number of items
|
||||||
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
|
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
|
||||||
|
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
|
||||||
double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
|
double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
|
||||||
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
|
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
|
||||||
|
ImGuiContext* Ctx; // [Internal] Parent UI context
|
||||||
void* TempData; // [Internal] Internal data
|
void* TempData; // [Internal] Internal data
|
||||||
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
|
|
||||||
|
|
||||||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need)
|
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need)
|
||||||
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
|
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
|
||||||
@ -3021,17 +3028,18 @@ struct ImGuiListClipper
|
|||||||
// - It is important that we are keeping those disabled by default so they don't leak in user space.
|
// - It is important that we are keeping those disabled by default so they don't leak in user space.
|
||||||
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
|
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
|
||||||
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
|
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
|
||||||
// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake.
|
|
||||||
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
|
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
|
||||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||||
// ImVec2 operators
|
// ImVec2 operators
|
||||||
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
||||||
|
inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
|
||||||
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
||||||
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
||||||
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
|
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
|
||||||
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||||
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
|
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
|
||||||
|
inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
|
||||||
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
|
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
|
||||||
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||||
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||||
@ -3043,12 +3051,20 @@ inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x =
|
|||||||
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
|
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
|
||||||
// ImVec4 operators
|
// ImVec4 operators
|
||||||
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
|
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
|
||||||
|
inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
|
||||||
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
|
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
|
||||||
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
|
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
|
||||||
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
|
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
|
||||||
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
|
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
|
||||||
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
|
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
|
||||||
|
inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
|
||||||
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
|
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
|
||||||
|
inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
|
||||||
|
inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
|
||||||
|
inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
|
||||||
|
inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
|
||||||
|
inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
|
||||||
|
inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
|
||||||
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
|
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
|
||||||
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
|
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
|
||||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||||
@ -3150,16 +3166,23 @@ enum ImGuiMultiSelectFlags_
|
|||||||
ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item.
|
ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item.
|
||||||
ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space.
|
ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space.
|
||||||
ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items.
|
ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items.
|
||||||
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope.
|
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting and moving mouse near edges of scope.
|
||||||
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused.
|
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused.
|
||||||
ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope.
|
ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope.
|
||||||
ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window.
|
ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window.
|
||||||
ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window.
|
ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window.
|
||||||
ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default)
|
ImGuiMultiSelectFlags_SelectOnAuto = 1 << 13, // Apply selection on mouse down when clicking on unselected item, on mouse up when clicking on selected item. (Default)
|
||||||
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
|
ImGuiMultiSelectFlags_SelectOnClickAlways = 1 << 14, // Apply selection on mouse down when clicking on any items. Prevents Drag and Drop from being used on multiple-selection, but allows e.g. BoxSelect to always reselect even when clicking inside an existing selection. (Excel style behavior)
|
||||||
|
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 15, // 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.
|
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
|
||||||
|
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
|
||||||
|
|
||||||
|
// Obsolete names
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
ImGuiMultiSelectFlags_SelectOnClick = ImGuiMultiSelectFlags_SelectOnAuto, // RENAMED in 1.92.6
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
|
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
|
||||||
@ -3772,7 +3795,7 @@ enum ImFontAtlasFlags_
|
|||||||
// - Call Build() + GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
|
// - Call Build() + GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
|
||||||
// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
|
// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
|
||||||
// Common pitfalls:
|
// Common pitfalls:
|
||||||
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
|
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persists up until the
|
||||||
// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
|
// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
|
||||||
// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
|
// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
|
||||||
// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
|
// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
|
||||||
@ -4034,8 +4057,10 @@ inline ImTextureID ImTextureRef::GetTexID() const
|
|||||||
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
|
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
|
||||||
inline ImTextureID ImDrawCmd::GetTexID() const
|
inline ImTextureID ImDrawCmd::GetTexID() const
|
||||||
{
|
{
|
||||||
// If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92)
|
// If you are getting this assert with ImTextureID_Invalid == 0 and your ImTextureID is used to store an index or an offset:
|
||||||
// must iterate and handle ImTextureData requests stored in ImDrawData::Textures[].
|
// - You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
|
||||||
|
// If you are getting this assert with a renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92+):
|
||||||
|
// - You must correctly iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. See docs/BACKENDS.md.
|
||||||
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
|
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
|
||||||
if (TexRef._TexData != NULL)
|
if (TexRef._TexData != NULL)
|
||||||
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
|
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
|
||||||
@ -4109,6 +4134,7 @@ struct ImGuiViewport
|
|||||||
// Helpers
|
// Helpers
|
||||||
ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
|
ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
|
||||||
ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); }
|
ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); }
|
||||||
|
IMGUI_API const char* GetDebugName() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -4318,12 +4344,11 @@ namespace ImGui
|
|||||||
IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||||
IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||||
IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||||
// OBSOLETED in 1.90.0 (from September 2023)
|
|
||||||
IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
|
|
||||||
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);
|
|
||||||
|
|
||||||
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
|
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
|
||||||
// OBSOLETED in 1.90.0 (from September 2023)
|
// OBSOLETED in 1.90.0 (from September 2023)
|
||||||
|
//IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
|
||||||
|
//IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
|
||||||
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||||
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||||
//inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); }
|
//inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); }
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (drawing and font code)
|
// (drawing and font code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1318,7 +1318,7 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
|
|||||||
{
|
{
|
||||||
const float arc_length = ImAbs(a_max - a_min);
|
const float arc_length = ImAbs(a_max - a_min);
|
||||||
const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
|
const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
|
||||||
const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length));
|
const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), 1);
|
||||||
_PathArcToN(center, radius, a_min, a_max, arc_segment_count);
|
_PathArcToN(center, radius, a_min, a_max, arc_segment_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3209,7 +3209,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
|
|||||||
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
||||||
if (font_cfg.Name[0] == '\0')
|
if (font_cfg.Name[0] == '\0')
|
||||||
{
|
{
|
||||||
// Store a short copy of filename into into the font name for convenience
|
// Store a short copy of filename into the font name for convenience
|
||||||
const char* p;
|
const char* p;
|
||||||
for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
|
for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
|
||||||
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%s", p);
|
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%s", p);
|
||||||
@ -3217,7 +3217,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
|
|||||||
return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
|
return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
|
// NB: Transfer ownership of 'font_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
|
||||||
ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
||||||
{
|
{
|
||||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||||
@ -3264,7 +3264,9 @@ void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont*
|
|||||||
shared_data->Font = new_font;
|
shared_data->Font = new_font;
|
||||||
if (ImGuiContext* ctx = shared_data->Context)
|
if (ImGuiContext* ctx = shared_data->Context)
|
||||||
{
|
{
|
||||||
if (ctx->FrameCount == 0 && old_font == NULL) // While this should work either way, we save ourselves the bother / debugging confusion of running ImGui code so early when it is not needed.
|
// While this should work either way, we save ourselves the bother / debugging confusion of running ImGui code so early when it is not needed.
|
||||||
|
// Also fixes erroneously rewriting style.FontSizeBase during init if adding default fonts.
|
||||||
|
if (old_font == NULL && ctx->Font == NULL && ctx->FontSizeBase == 0.0f)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ctx->IO.FontDefault == old_font)
|
if (ctx->IO.FontDefault == old_font)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (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.
|
||||||
@ -545,7 +545,7 @@ inline float ImLinearSweep(float current, float target, float speed) { if (cu
|
|||||||
inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
|
inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
|
||||||
inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||||
inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
|
inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
|
||||||
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / n; avg += sample / n; return avg; }
|
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / (float)n; avg += sample / (float)n; return avg; }
|
||||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||||
|
|
||||||
// Helpers: Geometry
|
// Helpers: Geometry
|
||||||
@ -1034,7 +1034,7 @@ enum ImGuiInputTextFlagsPrivate_
|
|||||||
{
|
{
|
||||||
// [Internal]
|
// [Internal]
|
||||||
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
|
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
|
||||||
ImGuiInputTextFlags_MergedItem = 1 << 27, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
|
ImGuiInputTextFlags_TempInput = 1 << 27, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
|
||||||
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 28, // For internal use by InputScalar() and TempInputScalar()
|
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 28, // For internal use by InputScalar() and TempInputScalar()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1044,12 +1044,11 @@ enum ImGuiButtonFlagsPrivate_
|
|||||||
ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event)
|
ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event)
|
||||||
ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using
|
ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using
|
||||||
ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item
|
ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item
|
||||||
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release)
|
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release). Prior to 2026/03/20 this implied ImGuiButtonFlags_NoHoldingActiveId but they are separate now.
|
||||||
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
|
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
|
||||||
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
|
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
|
||||||
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead.
|
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead.
|
||||||
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
|
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
|
||||||
ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable.
|
|
||||||
//ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press
|
//ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press
|
||||||
//ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
|
//ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
|
||||||
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
|
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
|
||||||
@ -1257,7 +1256,8 @@ struct IMGUI_API ImGuiInputTextState
|
|||||||
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
||||||
bool CursorCenterY; // set when we want scrolling to be centered over the cursor position (while resizing a word-wrapping field)
|
bool CursorCenterY; // set when we want scrolling to be centered over the cursor position (while resizing a word-wrapping field)
|
||||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||||
bool Edited; // edited this frame
|
bool EditedBefore; // edited since activated
|
||||||
|
bool EditedThisFrame; // edited this frame
|
||||||
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
|
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
|
||||||
ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s
|
ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s
|
||||||
int ReloadSelectionStart;
|
int ReloadSelectionStart;
|
||||||
@ -1270,6 +1270,7 @@ struct IMGUI_API ImGuiInputTextState
|
|||||||
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
|
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
|
||||||
void OnCharPressed(unsigned int c);
|
void OnCharPressed(unsigned int c);
|
||||||
float GetPreferredOffsetX() const;
|
float GetPreferredOffsetX() const;
|
||||||
|
const char* GetText() { return TextA.Data ? TextA.Data : ""; }
|
||||||
|
|
||||||
// Cursor & Selection
|
// Cursor & Selection
|
||||||
void CursorAnimReset();
|
void CursorAnimReset();
|
||||||
@ -1527,8 +1528,8 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
|
|||||||
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
|
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
|
||||||
#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
|
#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
|
||||||
#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
|
#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
|
||||||
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
|
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft // Toggle menu layer. Hold to enable Windowing.
|
||||||
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
|
#define ImGuiKey_NavGamepadContextMenu ImGuiKey_GamepadFaceUp // Open context menu (same as Shift+F10)
|
||||||
|
|
||||||
enum ImGuiInputEventType
|
enum ImGuiInputEventType
|
||||||
{
|
{
|
||||||
@ -2139,7 +2140,7 @@ struct ImGuiViewportP : public ImGuiViewport
|
|||||||
float LastAlpha;
|
float LastAlpha;
|
||||||
bool LastFocusedHadNavWindow;// Instead of maintaining a LastFocusedWindow (which may harder to correctly maintain), we merely store weither NavWindow != NULL last time the viewport was focused.
|
bool LastFocusedHadNavWindow;// Instead of maintaining a LastFocusedWindow (which may harder to correctly maintain), we merely store weither NavWindow != NULL last time the viewport was focused.
|
||||||
short PlatformMonitor;
|
short PlatformMonitor;
|
||||||
int BgFgDrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used
|
float BgFgDrawListsLastTimeActive[2]; // Last frame number the background (0) and foreground (1) draw lists were used
|
||||||
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
|
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
|
||||||
ImDrawData DrawDataP;
|
ImDrawData DrawDataP;
|
||||||
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
|
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
|
||||||
@ -2156,7 +2157,7 @@ struct ImGuiViewportP : public ImGuiViewport
|
|||||||
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
|
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
|
||||||
ImVec2 BuildWorkInsetMax; // "
|
ImVec2 BuildWorkInsetMax; // "
|
||||||
|
|
||||||
ImGuiViewportP() { Window = NULL; Idx = -1; LastFrameActive = BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = LastFocusedStampCount = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; LastFocusedHadNavWindow = false; PlatformMonitor = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; LastPlatformPos = LastPlatformSize = LastRendererSize = ImVec2(FLT_MAX, FLT_MAX); }
|
ImGuiViewportP() { Window = NULL; Idx = -1; LastFrameActive = LastFocusedStampCount = -1; BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0f; LastNameHash = 0; Alpha = LastAlpha = 1.0f; LastFocusedHadNavWindow = false; PlatformMonitor = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; LastPlatformPos = LastPlatformSize = LastRendererSize = ImVec2(FLT_MAX, FLT_MAX); }
|
||||||
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
|
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
|
||||||
void ClearRequestFlags() { PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; }
|
void ClearRequestFlags() { PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; }
|
||||||
|
|
||||||
@ -2376,6 +2377,8 @@ struct ImGuiContextHook
|
|||||||
ImGuiContextHook() { memset((void*)this, 0, sizeof(*this)); }
|
ImGuiContextHook() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] ImGuiContext (main Dear ImGui context)
|
// [SECTION] ImGuiContext (main Dear ImGui context)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2529,6 +2532,7 @@ struct ImGuiContext
|
|||||||
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
||||||
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
||||||
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
||||||
|
ImGuiItemFlags NavIdItemFlags;
|
||||||
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
|
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
|
||||||
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
||||||
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
||||||
@ -2536,6 +2540,8 @@ struct ImGuiContext
|
|||||||
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
||||||
ImGuiID NavHighlightActivatedId;
|
ImGuiID NavHighlightActivatedId;
|
||||||
float NavHighlightActivatedTimer;
|
float NavHighlightActivatedTimer;
|
||||||
|
ImGuiID NavOpenContextMenuItemId;
|
||||||
|
ImGuiID NavOpenContextMenuWindowId;
|
||||||
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_Gamepad
|
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
|
||||||
@ -2665,6 +2671,7 @@ struct ImGuiContext
|
|||||||
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
||||||
ImFontBaked InputTextPasswordFontBackupBaked;
|
ImFontBaked InputTextPasswordFontBackupBaked;
|
||||||
ImFontFlags InputTextPasswordFontBackupFlags;
|
ImFontFlags InputTextPasswordFontBackupFlags;
|
||||||
|
ImGuiID InputTextReactivateId; // ID of InputText to reactivate on next frame (for io.ConfigInputTextEnterKeepActive behavior)
|
||||||
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
|
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
|
||||||
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
||||||
int BeginMenuDepth;
|
int BeginMenuDepth;
|
||||||
@ -2712,8 +2719,11 @@ struct ImGuiContext
|
|||||||
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
|
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
|
||||||
ImChunkStream<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries
|
ImChunkStream<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries
|
||||||
ImChunkStream<ImGuiTableSettings> SettingsTables; // ImGuiTable .ini settings entries
|
ImChunkStream<ImGuiTableSettings> SettingsTables; // ImGuiTable .ini settings entries
|
||||||
|
|
||||||
|
// Hooks
|
||||||
ImVector<ImGuiContextHook> Hooks; // Hooks for extensions (e.g. test engine)
|
ImVector<ImGuiContextHook> Hooks; // Hooks for extensions (e.g. test engine)
|
||||||
ImGuiID HookIdNext; // Next available HookId
|
ImGuiID HookIdNext; // Next available HookId
|
||||||
|
ImGuiDemoMarkerCallback DemoMarkerCallback;
|
||||||
|
|
||||||
// Localization
|
// Localization
|
||||||
const char* LocalizationTable[ImGuiLocKey_COUNT];
|
const char* LocalizationTable[ImGuiLocKey_COUNT];
|
||||||
@ -3269,8 +3279,9 @@ struct IMGUI_API ImGuiTable
|
|||||||
ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0.
|
ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0.
|
||||||
ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame.
|
ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame.
|
||||||
ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
|
ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
|
||||||
|
ImGuiTableColumnIdx LastHeldHeaderColumn; // Index of column header being held from previous frame.
|
||||||
ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared)
|
ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared)
|
||||||
ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1
|
ImGuiTableColumnIdx ReorderColumnDstOrder; // Requested display order of column being reordered.
|
||||||
ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column.
|
ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column.
|
||||||
ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
|
ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
|
||||||
ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column.
|
ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column.
|
||||||
@ -3562,6 +3573,8 @@ namespace ImGui
|
|||||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||||
IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
|
IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
|
||||||
|
IMGUI_API bool IsPopupOpenRequestForItem(ImGuiPopupFlags flags, ImGuiID id);
|
||||||
|
IMGUI_API bool IsPopupOpenRequestForWindow(ImGuiPopupFlags flags);
|
||||||
|
|
||||||
// Tooltips
|
// Tooltips
|
||||||
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
|
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
|
||||||
@ -3841,6 +3854,7 @@ namespace ImGui
|
|||||||
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
|
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
|
||||||
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
||||||
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
||||||
|
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
||||||
IMGUI_API void TableRemove(ImGuiTable* table);
|
IMGUI_API void TableRemove(ImGuiTable* table);
|
||||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
||||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
||||||
@ -3933,6 +3947,7 @@ namespace ImGui
|
|||||||
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
|
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
|
||||||
IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
|
IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
|
||||||
IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
|
IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
|
||||||
|
IMGUI_API void ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis);
|
||||||
|
|
||||||
// Widgets low-level behaviors
|
// Widgets low-level behaviors
|
||||||
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
||||||
@ -3945,15 +3960,14 @@ namespace ImGui
|
|||||||
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
|
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
|
||||||
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
|
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
|
||||||
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
||||||
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
|
|
||||||
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
||||||
IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
|
IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
|
||||||
|
|
||||||
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
|
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
|
||||||
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
|
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
|
||||||
// e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
|
// e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
|
||||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
|
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
|
||||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
|
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
|
||||||
template<typename T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
|
template<typename T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
|
||||||
@ -3971,7 +3985,7 @@ namespace ImGui
|
|||||||
// InputText
|
// InputText
|
||||||
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
|
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
|
||||||
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
|
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
|
||||||
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
|
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
|
||||||
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
|
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
|
||||||
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
|
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
|
||||||
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
|
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
|
||||||
@ -4007,6 +4021,9 @@ namespace ImGui
|
|||||||
IMGUI_API bool BeginErrorTooltip();
|
IMGUI_API bool BeginErrorTooltip();
|
||||||
IMGUI_API void EndErrorTooltip();
|
IMGUI_API void EndErrorTooltip();
|
||||||
|
|
||||||
|
// Demo Doc Marker for e.g. imgui_explorer
|
||||||
|
IMGUI_API void DemoMarker(const char* file, int line, const char* section);
|
||||||
|
|
||||||
// Debug Tools
|
// Debug Tools
|
||||||
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
|
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
|
||||||
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
|
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
|
||||||
@ -4027,7 +4044,7 @@ namespace ImGui
|
|||||||
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
||||||
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
||||||
IMGUI_API void DebugNodeFont(ImFont* font);
|
IMGUI_API void DebugNodeFont(ImFont* font);
|
||||||
IMGUI_API void DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
IMGUI_API void DebugNodeFontGlyphsForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
||||||
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
||||||
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
|
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
|
||||||
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (tables and columns code)
|
// (tables and columns code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -585,7 +585,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
|
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
|
||||||
table->InstanceInteracted = -1;
|
table->InstanceInteracted = -1;
|
||||||
table->ContextPopupColumn = -1;
|
table->ContextPopupColumn = -1;
|
||||||
table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1;
|
table->ReorderColumn = table->ReorderColumnDstOrder = table->ResizedColumn = table->LastResizedColumn = -1;
|
||||||
table->AutoFitSingleColumn = -1;
|
table->AutoFitSingleColumn = -1;
|
||||||
table->HoveredColumnBody = table->HoveredColumnBorder = -1;
|
table->HoveredColumnBody = table->HoveredColumnBorder = -1;
|
||||||
for (int n = 0; n < columns_count; n++)
|
for (int n = 0; n < columns_count; n++)
|
||||||
@ -699,25 +699,23 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle reordering request
|
// Handle reordering request
|
||||||
// Note: we don't clear ReorderColumn after handling the request (FIXME: clarify why or add a test).
|
//// Note: we don't clear ReorderColumn after handling the request (FIXME: clarify why or add a test).
|
||||||
if (table->InstanceCurrent == 0)
|
if (table->InstanceCurrent == 0)
|
||||||
{
|
{
|
||||||
if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1)
|
table->LastHeldHeaderColumn = table->HeldHeaderColumn;
|
||||||
table->ReorderColumn = -1;
|
|
||||||
table->HeldHeaderColumn = -1;
|
table->HeldHeaderColumn = -1;
|
||||||
if (table->ReorderColumn != -1 && table->ReorderColumnDir != 0)
|
if (table->ReorderColumn != -1 && table->ReorderColumnDstOrder != -1)
|
||||||
{
|
{
|
||||||
// We need to handle reordering across hidden columns.
|
TableSetColumnDisplayOrder(table, table->ReorderColumn, table->ReorderColumnDstOrder);
|
||||||
// In the configuration below, moving C to the right of E will lead to:
|
table->ReorderColumnDstOrder = -1;
|
||||||
// ... C [D] E ---> ... [D] E C (Column name/index)
|
|
||||||
// ... 2 3 4 ... 2 3 4 (Display order)
|
|
||||||
IM_ASSERT(table->ReorderColumnDir == -1 || table->ReorderColumnDir == +1);
|
|
||||||
IM_ASSERT(table->Flags & ImGuiTableFlags_Reorderable);
|
|
||||||
ImGuiTableColumn* src_column = &table->Columns[table->ReorderColumn];
|
|
||||||
ImGuiTableColumn* dst_column = &table->Columns[(table->ReorderColumnDir < 0) ? src_column->PrevEnabledColumn : src_column->NextEnabledColumn];
|
|
||||||
TableSetColumnDisplayOrder(table, table->ReorderColumn, dst_column->DisplayOrder);
|
|
||||||
table->ReorderColumnDir = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Release
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.ActiveId == 0) // FIXME: Need to revisit. See 38f5e5a.
|
||||||
|
table->ReorderColumn = -1;
|
||||||
|
//if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1)
|
||||||
|
// table->ReorderColumn = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle display order reset request
|
// Handle display order reset request
|
||||||
@ -730,8 +728,7 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that TableSetupScrollFreeze() enforce a display order range for frozen columns.
|
// Apply immediately. See TableQueueSetColumnDisplayOrder() for additional checks/constraints.
|
||||||
// So reordering a column across the frozen column barrier is illegal and will be undone.
|
|
||||||
void ImGui::TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order)
|
void ImGui::TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order)
|
||||||
{
|
{
|
||||||
IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
|
IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
|
||||||
@ -755,6 +752,39 @@ void ImGui::TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_
|
|||||||
table->IsSettingsDirty = true;
|
table->IsSettingsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int TableGetMaxDisplayOrderAllowed(ImGuiTable* table, int src_order, int dst_order)
|
||||||
|
{
|
||||||
|
dst_order = ImClamp(dst_order, 0, table->ColumnsCount - 1);
|
||||||
|
if (src_order == dst_order)
|
||||||
|
return dst_order;
|
||||||
|
|
||||||
|
// Cannot cross over the frozen column limit when interactively reordering.
|
||||||
|
// TableSetupScrollFreeze() enforce a display order range for frozen columns. Reordering across the frozen column barrier is illegal and will be undone.
|
||||||
|
if (table->FreezeColumnsRequest > 0)
|
||||||
|
dst_order = (src_order < table->FreezeColumnsRequest) ? ImMin(dst_order, (int)table->FreezeColumnsRequest - 1) : ImMax(dst_order, (int)table->FreezeColumnsRequest);
|
||||||
|
|
||||||
|
// Cannot cross over a column with the ImGuiTableColumnFlags_NoReorder flag.
|
||||||
|
int reorder_dir = (src_order < dst_order) ? +1 : -1;
|
||||||
|
for (int order_n = src_order; (src_order < dst_order && order_n <= dst_order) || (dst_order < src_order && order_n >= dst_order); order_n += reorder_dir)
|
||||||
|
if (table->Columns[table->DisplayOrderToIndex[order_n]].Flags & ImGuiTableColumnFlags_NoReorder)
|
||||||
|
{
|
||||||
|
dst_order = (order_n == src_order) ? src_order : order_n - reorder_dir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return dst_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reorder requested by user interaction.
|
||||||
|
void ImGui::TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order)
|
||||||
|
{
|
||||||
|
const int src_order = table->Columns[column_n].DisplayOrder;
|
||||||
|
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
|
||||||
|
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)-1;
|
||||||
|
dst_order = TableGetMaxDisplayOrderAllowed(table, src_order, dst_order);
|
||||||
|
if (dst_order != src_order)
|
||||||
|
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)dst_order;
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
|
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
|
||||||
static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in)
|
static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in)
|
||||||
{
|
{
|
||||||
@ -1062,7 +1092,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
|
|
||||||
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
|
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
|
||||||
// Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping.
|
// Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping.
|
||||||
int visible_n = 0;
|
|
||||||
bool has_at_least_one_column_requesting_output = false;
|
bool has_at_least_one_column_requesting_output = false;
|
||||||
bool offset_x_frozen = (table->FreezeColumnsCount > 0);
|
bool offset_x_frozen = (table->FreezeColumnsCount > 0);
|
||||||
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
|
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
|
||||||
@ -1077,7 +1106,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
// Initial nav layer: using FreezeRowsCount, NOT FreezeRowsRequest, so Header line changes layer when frozen
|
// Initial nav layer: using FreezeRowsCount, NOT FreezeRowsRequest, so Header line changes layer when frozen
|
||||||
column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : (ImGuiNavLayer)table->NavLayer);
|
column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : (ImGuiNavLayer)table->NavLayer);
|
||||||
|
|
||||||
if (offset_x_frozen && table->FreezeColumnsCount == visible_n)
|
if (offset_x_frozen && table->FreezeColumnsCount == order_n)
|
||||||
{
|
{
|
||||||
offset_x += work_rect.Min.x - table->OuterRect.Min.x;
|
offset_x += work_rect.Min.x - table->OuterRect.Min.x;
|
||||||
offset_x_frozen = false;
|
offset_x_frozen = false;
|
||||||
@ -1197,11 +1226,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
column->CannotSkipItemsQueue >>= 1;
|
column->CannotSkipItemsQueue >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible_n < table->FreezeColumnsCount)
|
if (order_n < table->FreezeColumnsCount)
|
||||||
host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x);
|
host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x);
|
||||||
|
|
||||||
offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
|
offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
|
||||||
visible_n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible.
|
// In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible.
|
||||||
@ -1282,7 +1310,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
|
|
||||||
// [Part 13] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns)
|
// [Part 13] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns)
|
||||||
if (table->FreezeColumnsRequest > 0)
|
if (table->FreezeColumnsRequest > 0)
|
||||||
table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x;
|
table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x; // FIXME-FROZEN
|
||||||
if (table->FreezeRowsRequest > 0)
|
if (table->FreezeRowsRequest > 0)
|
||||||
table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight;
|
table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight;
|
||||||
table_instance->LastFrozenHeight = 0.0f;
|
table_instance->LastFrozenHeight = 0.0f;
|
||||||
@ -1674,18 +1702,6 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
|
|||||||
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
|
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
|
||||||
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
|
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
|
||||||
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
|
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
|
||||||
|
|
||||||
// Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.
|
|
||||||
// FIXME-TABLE: This work for preserving 2143 into 21|43. How about 4321 turning into 21|43? (preserve relative order in each section)
|
|
||||||
for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)
|
|
||||||
{
|
|
||||||
int order_n = table->DisplayOrderToIndex[column_n];
|
|
||||||
if (order_n != column_n && order_n >= table->FreezeColumnsRequest)
|
|
||||||
{
|
|
||||||
ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder);
|
|
||||||
ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -3121,7 +3137,7 @@ void ImGui::TableHeadersRow()
|
|||||||
const int columns_count = TableGetColumnCount();
|
const int columns_count = TableGetColumnCount();
|
||||||
for (int column_n = 0; column_n < columns_count; column_n++)
|
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||||
{
|
{
|
||||||
if (!TableSetColumnIndex(column_n))
|
if (!TableSetColumnIndex(column_n) && table->LastHeldHeaderColumn != column_n)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Push an id to allow empty/unnamed headers. This is also idiomatic as it ensure there is a consistent ID path to access columns (for e.g. automation)
|
// Push an id to allow empty/unnamed headers. This is also idiomatic as it ensure there is a consistent ID path to access columns (for e.g. automation)
|
||||||
@ -3224,21 +3240,19 @@ void ImGui::TableHeader(const char* label)
|
|||||||
// FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone.
|
// FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone.
|
||||||
if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive)
|
if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive)
|
||||||
{
|
{
|
||||||
// While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x
|
// - While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x
|
||||||
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
|
// - We need to handle reordering across hidden columns.
|
||||||
|
// In the configuration below, moving C to the right of E will lead to:
|
||||||
|
// ... C [D] E ---> ... [D] E C (Column name/index)
|
||||||
|
// ... 2 3 4 ... 2 3 4 (Display order)
|
||||||
|
// - The other constraints are enforced by TableQueueSetColumnDisplayOrder() which might early out.
|
||||||
table->InstanceInteracted = table->InstanceCurrent;
|
table->InstanceInteracted = table->InstanceCurrent;
|
||||||
|
|
||||||
// We don't reorder: through the frozen<>unfrozen line, or through a column that is marked with ImGuiTableColumnFlags_NoReorder.
|
|
||||||
if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x)
|
if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x)
|
||||||
if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL)
|
if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL)
|
||||||
if (!((column->Flags | prev_column->Flags) & ImGuiTableColumnFlags_NoReorder))
|
TableQueueSetColumnDisplayOrder(table, column_n, prev_column->DisplayOrder);
|
||||||
if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (prev_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
|
|
||||||
table->ReorderColumnDir = -1;
|
|
||||||
if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x)
|
if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x)
|
||||||
if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL)
|
if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL)
|
||||||
if (!((column->Flags | next_column->Flags) & ImGuiTableColumnFlags_NoReorder))
|
TableQueueSetColumnDisplayOrder(table, column_n, next_column->DisplayOrder);
|
||||||
if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (next_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
|
|
||||||
table->ReorderColumnDir = +1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort order arrow
|
// Sort order arrow
|
||||||
@ -3277,7 +3291,7 @@ void ImGui::TableHeader(const char* label)
|
|||||||
SetItemTooltip("%.*s", (int)(label_end - label), label);
|
SetItemTooltip("%.*s", (int)(label_end - label), label);
|
||||||
|
|
||||||
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
|
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
|
||||||
if (IsMouseReleased(1) && IsItemHovered())
|
if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id))
|
||||||
TableOpenContextMenu(column_n);
|
TableOpenContextMenu(column_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3294,7 +3308,7 @@ void ImGui::TableAngledHeadersRow()
|
|||||||
// Which column needs highlight?
|
// Which column needs highlight?
|
||||||
const ImGuiID row_id = GetID("##AngledHeaders");
|
const ImGuiID row_id = GetID("##AngledHeaders");
|
||||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||||
int highlight_column_n = table->HighlightColumnHeader;
|
int highlight_column_n = (table->LastHeldHeaderColumn != -1) ? table->LastHeldHeaderColumn : table->HighlightColumnHeader;
|
||||||
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
|
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
|
||||||
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
|
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
|
||||||
highlight_column_n = table->HoveredColumnBody;
|
highlight_column_n = table->HoveredColumnBody;
|
||||||
@ -3348,13 +3362,14 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
|||||||
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
|
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
|
||||||
|
|
||||||
// Declare row, override and draw our own background
|
// Declare row, override and draw our own background
|
||||||
|
// FIXME-TABLE: Generally broken when overlapping frozen columns limit.
|
||||||
TableNextRow(ImGuiTableRowFlags_Headers, row_height);
|
TableNextRow(ImGuiTableRowFlags_Headers, row_height);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2);
|
const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2);
|
||||||
table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
|
table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
|
||||||
float clip_rect_min_x = table->BgClipRect.Min.x;
|
float clip_rect_min_x = table->BgClipRect.Min.x;
|
||||||
if (table->FreezeColumnsCount > 0)
|
if (table->FreezeColumnsCount > 0)
|
||||||
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
|
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX);
|
||||||
TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
|
TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
|
||||||
PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
|
PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
|
||||||
draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
|
draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
|
||||||
@ -3490,6 +3505,36 @@ bool ImGui::TableBeginContextMenuPopup(ImGuiTable* table)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Copied from MenuItem() for the purpose of being able to pass _SelectOnRelease (#9312)
|
||||||
|
static bool MenuItemForColumnReorder(const char* label, bool selected, bool enabled)
|
||||||
|
{
|
||||||
|
using namespace ImGui;
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
|
||||||
|
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||||
|
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||||
|
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
||||||
|
float min_w = offsets->DeclColumns(0.0f, label_size.x, 0.0f, checkmark_w); // Feedback for next frame
|
||||||
|
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||||
|
ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
|
|
||||||
|
ImGuiID id = GetID(label);
|
||||||
|
ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SpanAvailWidth;
|
||||||
|
if (g.ActiveId == id)
|
||||||
|
selectable_flags |= ImGuiSelectableFlags_Highlight; // Stays highlighted while dragging.
|
||||||
|
const bool has_been_moved = (g.ActiveId == id) && g.ActiveIdHasBeenEditedBefore; // But disable toggling once moved.
|
||||||
|
|
||||||
|
BeginDisabled(!enabled); // Don't use ImGuiSelectableFlags_Disabled so that Check mark is also affected.
|
||||||
|
bool ret = Selectable(label, false, selectable_flags, ImVec2(min_w, label_size.y)) && !has_been_moved; // Can't use IsMouseDragging(0) as button is released already.
|
||||||
|
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) && selected)
|
||||||
|
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
|
||||||
|
EndDisabled();
|
||||||
|
|
||||||
|
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Output context menu into current window (generally a popup)
|
// Output context menu into current window (generally a popup)
|
||||||
// FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data?
|
// FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data?
|
||||||
// Sections to display are pulled from 'flags_for_section_to_display', which is typically == table->Flags.
|
// Sections to display are pulled from 'flags_for_section_to_display', which is typically == table->Flags.
|
||||||
@ -3506,17 +3551,17 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool want_separator = false;
|
bool want_separator = false;
|
||||||
const int column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1;
|
const int context_column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1;
|
||||||
ImGuiTableColumn* column = (column_n != -1) ? &table->Columns[column_n] : NULL;
|
ImGuiTableColumn* context_column = (context_column_n != -1) ? &table->Columns[context_column_n] : NULL;
|
||||||
|
|
||||||
// Sizing
|
// Sizing
|
||||||
if (flags_for_section_to_display & ImGuiTableFlags_Resizable)
|
if (flags_for_section_to_display & ImGuiTableFlags_Resizable)
|
||||||
{
|
{
|
||||||
if (column != NULL)
|
if (context_column != NULL)
|
||||||
{
|
{
|
||||||
const bool can_resize = !(column->Flags & ImGuiTableColumnFlags_NoResize) && column->IsEnabled;
|
const bool can_resize = !(context_column->Flags & ImGuiTableColumnFlags_NoResize) && context_column->IsEnabled;
|
||||||
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableSizeOne), NULL, false, can_resize)) // "###SizeOne"
|
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableSizeOne), NULL, false, can_resize)) // "###SizeOne"
|
||||||
TableSetColumnWidthAutoSingle(table, column_n);
|
TableSetColumnWidthAutoSingle(table, context_column_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* size_all_desc;
|
const char* size_all_desc;
|
||||||
@ -3565,23 +3610,47 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
|
|||||||
Separator();
|
Separator();
|
||||||
want_separator = true;
|
want_separator = true;
|
||||||
|
|
||||||
|
// While reordering: we calculate min/max allowed range once here so we can avoid a O(N log N) in the loop (because the query itself does a sweep scan).
|
||||||
|
// This assume that reordering constraints output a single range, otherwise would need to either call TableGetMaxDisplayOrderAllowed() for each item below, or cache this once per frame into columns.
|
||||||
|
const bool is_reordering = (g.ActiveId != 0 && g.ActiveIdWindow == g.CurrentWindow && table->ReorderColumn != -1 && g.ActiveIdHasBeenEditedBefore); // FIXME: This is a bit of a hack.
|
||||||
|
const int reorder_src_order = is_reordering ? table->Columns[table->ReorderColumn].DisplayOrder : -1;
|
||||||
|
const int reorder_min_order = is_reordering ? TableGetMaxDisplayOrderAllowed(table, reorder_src_order, 0) : 0;
|
||||||
|
const int reorder_max_order = is_reordering ? TableGetMaxDisplayOrderAllowed(table, reorder_src_order, table->ColumnsCount - 1) : table->ColumnsCount - 1;
|
||||||
PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
|
PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
|
||||||
for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
|
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||||
{
|
{
|
||||||
ImGuiTableColumn* other_column = &table->Columns[other_column_n];
|
const int column_n = table->DisplayOrderToIndex[order_n];
|
||||||
if (other_column->Flags & ImGuiTableColumnFlags_Disabled)
|
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||||
|
if (column->Flags & ImGuiTableColumnFlags_Disabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const char* name = TableGetColumnName(table, other_column_n);
|
const char* name = TableGetColumnName(table, column_n);
|
||||||
if (name == NULL || name[0] == 0)
|
if (name == NULL || name[0] == 0)
|
||||||
name = "<Unknown>";
|
name = "<Unknown>";
|
||||||
|
|
||||||
// Make sure we can't hide the last active column
|
// Make sure we can't hide the last active column
|
||||||
bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
|
bool menu_item_enabled = (column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
|
||||||
if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
|
if (column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
|
||||||
menu_item_active = false;
|
menu_item_enabled = false;
|
||||||
if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active))
|
if (is_reordering && (column->DisplayOrder < reorder_min_order || column->DisplayOrder > reorder_max_order))
|
||||||
other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled;
|
menu_item_enabled = false;
|
||||||
|
if (MenuItemForColumnReorder(name, column->IsUserEnabled, menu_item_enabled))
|
||||||
|
column->IsUserEnabledNextFrame = !column->IsUserEnabled;
|
||||||
|
|
||||||
|
// Drag to reorder
|
||||||
|
// FIXME: It is currently not possible to reorder columns marked with ImGuiTableColumnFlags_NoHide.
|
||||||
|
if (IsItemActive() && IsMouseDragging(0) && g.ActiveIdSource == ImGuiInputSource_Mouse && (table->Flags & ImGuiTableFlags_Reorderable))
|
||||||
|
{
|
||||||
|
g.ActiveIdHasBeenEditedBefore = true; // Disable toggle in MenuItemForColumnReorder() + start dimming to display allowed reorder targets.
|
||||||
|
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
|
||||||
|
if (!IsItemHovered())
|
||||||
|
{
|
||||||
|
int reorder_dir = (g.IO.MousePos.y < (g.LastItemData.Rect.Min.y + g.LastItemData.Rect.Max.y) * 0.5f) ? -1 : +1;
|
||||||
|
float reorder_amount = (reorder_dir < 0 ? g.LastItemData.Rect.Min.y - g.IO.MousePos.y : g.IO.MousePos.y - g.LastItemData.Rect.Max.y) / g.LastItemData.Rect.GetHeight();
|
||||||
|
int dst_order = column->DisplayOrder + (int)ImCeil(reorder_amount) * reorder_dir; // Estimated target order, will be validated and clamped.
|
||||||
|
TableQueueSetColumnDisplayOrder(table, column_n, dst_order);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PopItemFlag();
|
PopItemFlag();
|
||||||
}
|
}
|
||||||
@ -4051,7 +4120,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||||||
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
|
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
|
||||||
BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
|
BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
|
||||||
BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder);
|
BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder);
|
||||||
BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn);
|
BulletText("ResizedColumn: %d, HeldHeaderColumn: %d, ReorderColumn: %d", table->LastResizedColumn, table->LastHeldHeaderColumn, table->ReorderColumn);
|
||||||
for (int n = 0; n < table->InstanceCurrent + 1; n++)
|
for (int n = 0; n < table->InstanceCurrent + 1; n++)
|
||||||
{
|
{
|
||||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, n);
|
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, n);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.6
|
// dear imgui, v1.92.7
|
||||||
// (widgets code)
|
// (widgets code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -653,6 +653,14 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|||||||
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flags & ImGuiButtonFlags_PressedOnRelease)
|
||||||
|
{
|
||||||
|
// FIXME: Traditionally ImGuiButtonFlags_PressedOnRelease never took ActiveId. Adding it in 2026-03-20 since ImGuiButtonFlags_NoHoldingActiveId can always be added.
|
||||||
|
// We don't yet perform an explicit ClearActiveID() to reduce scope of change, but this possibility could be investigated.
|
||||||
|
if (!(flags & ImGuiButtonFlags_NoHoldingActiveId))
|
||||||
|
SetActiveID(id, window); // Hold on ID
|
||||||
|
g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flags & ImGuiButtonFlags_PressedOnRelease)
|
if (flags & ImGuiButtonFlags_PressedOnRelease)
|
||||||
{
|
{
|
||||||
@ -919,7 +927,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
|
|||||||
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
||||||
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
||||||
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
||||||
const float cross_thickness = 1.0f; // FIXME-DPI
|
const float cross_thickness = 1.0f * (float)(int)g.Style._MainScale; // FIXME-DPI
|
||||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
|
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
|
||||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
|
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
|
||||||
|
|
||||||
@ -980,6 +988,16 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
|
|||||||
return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y + border_top, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size);
|
return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y + border_top, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGui::ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis)
|
||||||
|
{
|
||||||
|
ImRect window_rect = window->RootWindow->Rect();
|
||||||
|
ImRect viewport_rect = window->Viewport->GetMainRect();
|
||||||
|
if (window_rect.Min[axis] == viewport_rect.Min[axis] && bb->Min[axis] > window_rect.Min[axis] && bb->Min[axis] - threshold <= window_rect.Min[axis])
|
||||||
|
bb->Min[axis] = window_rect.Min[axis];
|
||||||
|
if (window_rect.Max[axis] == viewport_rect.Max[axis] && bb->Max[axis] < window_rect.Max[axis] && bb->Max[axis] + threshold >= window_rect.Max[axis])
|
||||||
|
bb->Max[axis] = window_rect.Max[axis];
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui::Scrollbar(ImGuiAxis axis)
|
void ImGui::Scrollbar(ImGuiAxis axis)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -1039,14 +1057,18 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
|
|||||||
IM_ASSERT(ImMax(size_contents_v, size_visible_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
|
IM_ASSERT(ImMax(size_contents_v, size_visible_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
|
||||||
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_visible_v), (ImS64)1);
|
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_visible_v), (ImS64)1);
|
||||||
const float grab_h_minsize = ImMin(bb.GetSize()[axis], style.GrabMinSize);
|
const float grab_h_minsize = ImMin(bb.GetSize()[axis], style.GrabMinSize);
|
||||||
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v);
|
const float grab_h_pixels = (float)(int)ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v);
|
||||||
const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
|
const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
|
||||||
|
|
||||||
|
// As a special thing, we allow scrollbar near the edge of a screen/viewport to be reachable with mouse at the extreme edge (#9276)
|
||||||
|
ImRect bb_hit = bb_frame;
|
||||||
|
ExtendHitBoxWhenNearViewportEdge(window, &bb_hit, g.Style.WindowBorderSize, (ImGuiAxis)(axis ^ 1));
|
||||||
|
|
||||||
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
|
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
|
||||||
bool held = false;
|
bool held = false;
|
||||||
bool hovered = false;
|
bool hovered = false;
|
||||||
ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav);
|
ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav);
|
||||||
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
|
ButtonBehavior(bb_hit, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
|
||||||
|
|
||||||
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_visible_v);
|
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_visible_v);
|
||||||
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
|
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
|
||||||
@ -1536,7 +1558,7 @@ bool ImGui::TextLink(const char* label)
|
|||||||
}
|
}
|
||||||
|
|
||||||
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
||||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
|
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||||
|
|
||||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||||
RenderText(bb.Min, label, label_end);
|
RenderText(bb.Min, label, label_end);
|
||||||
@ -1671,9 +1693,13 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness)
|
|||||||
|
|
||||||
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
|
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
|
||||||
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
|
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
|
||||||
const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
|
|
||||||
|
// Between 1.71 and 1.92.7, we maintained a hack where a 1.0f thin Separator() would not impact layout.
|
||||||
|
// This was mostly chosen to allow backward compatibility with user's code assuming zero-height when calculating height for layout (e.g. bottom alignment of a status bar).
|
||||||
|
// In order to handle scaling we need to scale separator thickness and it would not makes sense to have a disparity depending on height.
|
||||||
|
////float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
|
||||||
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness));
|
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness));
|
||||||
ItemSize(ImVec2(0.0f, thickness_for_layout));
|
ItemSize(ImVec2(0.0f, thickness));
|
||||||
|
|
||||||
if (ItemAdd(bb, 0))
|
if (ItemAdd(bb, 0))
|
||||||
{
|
{
|
||||||
@ -1699,14 +1725,13 @@ void ImGui::Separator()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Those flags should eventually be configurable by the user
|
// Those flags should eventually be configurable by the user
|
||||||
// FIXME: We cannot g.Style.SeparatorTextBorderSize for thickness as it relates to SeparatorText() which is a decorated separator, not defaulting to 1.0f.
|
|
||||||
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
||||||
|
|
||||||
// Only applies to legacy Columns() api as they relied on Separator() a lot.
|
// Only applies to legacy Columns() api as they relied on Separator() a lot.
|
||||||
if (window->DC.CurrentColumns)
|
if (window->DC.CurrentColumns)
|
||||||
flags |= ImGuiSeparatorFlags_SpanAllColumns;
|
flags |= ImGuiSeparatorFlags_SpanAllColumns;
|
||||||
|
|
||||||
SeparatorEx(flags, 1.0f);
|
SeparatorEx(flags, g.Style.SeparatorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
|
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
|
||||||
@ -2209,30 +2234,6 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa
|
|||||||
return value_changed;
|
return value_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
|
||||||
|
|
||||||
struct ImGuiGetNameFromIndexOldToNewCallbackData { void* UserData; bool (*OldCallback)(void*, int, const char**); };
|
|
||||||
static const char* ImGuiGetNameFromIndexOldToNewCallback(void* user_data, int idx)
|
|
||||||
{
|
|
||||||
ImGuiGetNameFromIndexOldToNewCallbackData* data = (ImGuiGetNameFromIndexOldToNewCallbackData*)user_data;
|
|
||||||
const char* s = NULL;
|
|
||||||
data->OldCallback(data->UserData, idx, &s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::ListBox(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int height_in_items)
|
|
||||||
{
|
|
||||||
ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter };
|
|
||||||
return ListBox(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, height_in_items);
|
|
||||||
}
|
|
||||||
bool ImGui::Combo(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int popup_max_height_in_items)
|
|
||||||
{
|
|
||||||
ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter };
|
|
||||||
return Combo(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, popup_max_height_in_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// [SECTION] Data Type and Data Formatting Helpers [Internal]
|
// [SECTION] Data Type and Data Formatting Helpers [Internal]
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -2592,9 +2593,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
|||||||
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
|
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
|
||||||
|
|
||||||
// Convert to parametric space, apply delta, convert back
|
// Convert to parametric space, apply delta, convert back
|
||||||
float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
float v_new_parametric = v_old_parametric + g.DragCurrentAccum;
|
float v_new_parametric = v_old_parametric + g.DragCurrentAccum;
|
||||||
v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
v_old_ref_for_accum_remainder = v_old_parametric;
|
v_old_ref_for_accum_remainder = v_old_parametric;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2611,7 +2612,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
|||||||
if (is_logarithmic)
|
if (is_logarithmic)
|
||||||
{
|
{
|
||||||
// Convert to parametric space, apply delta, convert back
|
// Convert to parametric space, apply delta, convert back
|
||||||
float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder);
|
g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2687,6 +2688,20 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
|
||||||
|
static bool TempInputIsClampEnabled(ImGuiSliderFlags flags, ImGuiDataType data_type, const void* p_min, const void* p_max)
|
||||||
|
{
|
||||||
|
if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
|
||||||
|
{
|
||||||
|
const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? ImGui::DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
|
||||||
|
if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
|
||||||
|
return true;
|
||||||
|
if (clamp_range_dir == 0)
|
||||||
|
return ImGui::DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
|
// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
|
||||||
// Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
|
// Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
|
||||||
bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
|
bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
|
||||||
@ -2752,16 +2767,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
|||||||
|
|
||||||
if (temp_input_is_active)
|
if (temp_input_is_active)
|
||||||
{
|
{
|
||||||
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
|
const bool clamp_enabled = TempInputIsClampEnabled(flags, data_type, p_min, p_max);
|
||||||
bool clamp_enabled = false;
|
|
||||||
if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
|
|
||||||
{
|
|
||||||
const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
|
|
||||||
if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
|
|
||||||
clamp_enabled = true;
|
|
||||||
else if (clamp_range_dir == 0)
|
|
||||||
clamp_enabled = DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
|
|
||||||
}
|
|
||||||
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
|
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2961,14 +2967,14 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
|
|||||||
|
|
||||||
// Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT)
|
// Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT)
|
||||||
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
|
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
|
||||||
float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
|
float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
|
||||||
{
|
{
|
||||||
if (v_min == v_max)
|
if (v_min == v_max)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
IM_UNUSED(data_type);
|
IM_UNUSED(data_type);
|
||||||
|
|
||||||
const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
|
const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
|
||||||
if (is_logarithmic)
|
if (logarithmic_zero_epsilon > 0.0f) // == is_logarithmic from caller
|
||||||
{
|
{
|
||||||
bool flipped = v_max < v_min;
|
bool flipped = v_max < v_min;
|
||||||
|
|
||||||
@ -3018,7 +3024,7 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
|
|||||||
|
|
||||||
// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT)
|
// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT)
|
||||||
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
|
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
|
||||||
TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
|
TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
|
||||||
{
|
{
|
||||||
// We special-case the extents because otherwise our logarithmic fudging can lead to "mathematically correct"
|
// We special-case the extents because otherwise our logarithmic fudging can lead to "mathematically correct"
|
||||||
// but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value. Also generally simpler.
|
// but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value. Also generally simpler.
|
||||||
@ -3028,7 +3034,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
|
|||||||
return v_max;
|
return v_max;
|
||||||
|
|
||||||
TYPE result = (TYPE)0;
|
TYPE result = (TYPE)0;
|
||||||
if (is_logarithmic)
|
if (logarithmic_zero_epsilon > 0.0f) // == is_logarithmic from caller
|
||||||
{
|
{
|
||||||
// Fudge min/max to avoid getting silly results close to zero
|
// Fudge min/max to avoid getting silly results close to zero
|
||||||
FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
|
FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
|
||||||
@ -3133,7 +3139,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
|||||||
const float mouse_abs_pos = g.IO.MousePos[axis];
|
const float mouse_abs_pos = g.IO.MousePos[axis];
|
||||||
if (g.ActiveIdIsJustActivated)
|
if (g.ActiveIdIsJustActivated)
|
||||||
{
|
{
|
||||||
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
if (axis == ImGuiAxis_Y)
|
if (axis == ImGuiAxis_Y)
|
||||||
grab_t = 1.0f - grab_t;
|
grab_t = 1.0f - grab_t;
|
||||||
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
||||||
@ -3188,7 +3194,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
|||||||
}
|
}
|
||||||
else if (g.SliderCurrentAccumDirty)
|
else if (g.SliderCurrentAccumDirty)
|
||||||
{
|
{
|
||||||
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
|
|
||||||
if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
|
if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
|
||||||
{
|
{
|
||||||
@ -3202,10 +3208,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
|||||||
clicked_t = ImSaturate(clicked_t + delta);
|
clicked_t = ImSaturate(clicked_t + delta);
|
||||||
|
|
||||||
// Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator
|
// Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator
|
||||||
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
|
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
|
||||||
v_new = RoundScalarWithFormatT<TYPE>(format, data_type, v_new);
|
v_new = RoundScalarWithFormatT<TYPE>(format, data_type, v_new);
|
||||||
float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
|
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta);
|
g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta);
|
||||||
@ -3223,7 +3229,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
|||||||
|
|
||||||
if (set_new_value)
|
if (set_new_value)
|
||||||
{
|
{
|
||||||
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
|
|
||||||
// Round to user desired precision based on format string
|
// Round to user desired precision based on format string
|
||||||
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
|
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
|
||||||
@ -3245,7 +3251,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Output grab position so it can be displayed by the caller
|
// Output grab position so it can be displayed by the caller
|
||||||
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||||
if (axis == ImGuiAxis_Y)
|
if (axis == ImGuiAxis_Y)
|
||||||
grab_t = 1.0f - grab_t;
|
grab_t = 1.0f - grab_t;
|
||||||
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
||||||
@ -3353,7 +3359,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
|||||||
if (temp_input_is_active)
|
if (temp_input_is_active)
|
||||||
{
|
{
|
||||||
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
|
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
|
||||||
const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0;
|
const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0; // Don't use TempInputIsClampEnabled()
|
||||||
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
|
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3695,27 +3701,33 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create text input in place of another active widget (e.g. used when doing a Ctrl+Click on drag/slider widgets)
|
// Create text input in place of another active widget (e.g. used when doing a Ctrl+Click on drag/slider widgets)
|
||||||
|
// - This must be submitted right after the item it is overlaying.
|
||||||
// FIXME: Facilitate using this in variety of other situations.
|
// FIXME: Facilitate using this in variety of other situations.
|
||||||
// FIXME: Among other things, setting ImGuiItemFlags_AllowDuplicateId in LastItemData is currently correct but
|
bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||||
// the expected relationship between TempInputXXX functions and LastItemData is a little fishy.
|
|
||||||
bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
|
|
||||||
{
|
{
|
||||||
// On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
|
// On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
|
||||||
// We clear ActiveID on the first frame to allow the InputText() taking it back.
|
// We clear ActiveID on the first frame to allow the InputText() taking it back.
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
|
||||||
const bool init = (g.TempInputId != id);
|
const bool init = (g.TempInputId != id);
|
||||||
if (init)
|
if (init)
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
|
|
||||||
g.CurrentWindow->DC.CursorPos = bb.Min;
|
ImVec2 backup_pos = window->DC.CursorPos;
|
||||||
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId;
|
window->DC.CursorPos = bb.Min;
|
||||||
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
|
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId; // Using ImGuiInputTextFlags_MergedItem above will skip ItemAdd() so we poke here.
|
||||||
|
bool value_changed = InputTextEx(label, NULL, buf, (int)buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_TempInput | ImGuiInputTextFlags_AutoSelectAll, callback, user_data);
|
||||||
|
KeepAliveID(id); // Not done because of ImGuiInputTextFlags_TempInput
|
||||||
if (init)
|
if (init)
|
||||||
{
|
{
|
||||||
// First frame we started displaying the InputText widget, we expect it to take the active id.
|
// First frame we started displaying the InputText widget, we expect it to take the active id.
|
||||||
IM_ASSERT(g.ActiveId == id);
|
IM_ASSERT(g.ActiveId == id);
|
||||||
g.TempInputId = g.ActiveId;
|
g.TempInputId = g.ActiveId;
|
||||||
}
|
}
|
||||||
|
if (g.ActiveId != id)
|
||||||
|
g.TempInputId = 0;
|
||||||
|
window->DC.CursorPos = backup_pos;
|
||||||
return value_changed;
|
return value_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3738,9 +3750,9 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
|
|||||||
|
|
||||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
||||||
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
|
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
|
||||||
bool value_changed = false;
|
if (!TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
|
||||||
if (TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
|
return false;
|
||||||
{
|
|
||||||
// Backup old value
|
// Backup old value
|
||||||
size_t data_type_size = type_info->Size;
|
size_t data_type_size = type_info->Size;
|
||||||
ImGuiDataTypeStorage data_backup;
|
ImGuiDataTypeStorage data_backup;
|
||||||
@ -3757,10 +3769,9 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
|
|||||||
|
|
||||||
// Only mark as edited if new value is different
|
// Only mark as edited if new value is different
|
||||||
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
|
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
|
||||||
value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
|
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
|
||||||
if (value_changed)
|
if (value_changed)
|
||||||
MarkItemEdited(id);
|
MarkItemEdited(id);
|
||||||
}
|
|
||||||
return value_changed;
|
return value_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3799,24 +3810,30 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
|||||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
|
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
|
||||||
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
|
||||||
|
|
||||||
bool value_changed = false;
|
const bool has_step_buttons = (p_step != NULL);
|
||||||
if (p_step == NULL)
|
const float button_size = has_step_buttons ? GetFrameHeight() : 0.0f;
|
||||||
|
bool ret;
|
||||||
|
if (has_step_buttons)
|
||||||
{
|
{
|
||||||
if (InputText(label, buf, IM_COUNTOF(buf), flags))
|
// With Step Buttons
|
||||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const float button_size = GetFrameHeight();
|
|
||||||
|
|
||||||
BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
|
BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
|
||||||
PushID(label);
|
PushID(label);
|
||||||
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
|
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
|
||||||
if (InputText("", buf, IM_COUNTOF(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
|
ret = InputText("", buf, IM_COUNTOF(buf), flags); // PushID(label) + "" gives us the expected ID from outside point of view
|
||||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
|
|
||||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
|
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Without Step Buttons
|
||||||
|
ret = InputText(label, buf, IM_COUNTOF(buf), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply
|
||||||
|
bool value_changed = ret ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||||
|
|
||||||
// Step buttons
|
// Step buttons
|
||||||
|
if (has_step_buttons)
|
||||||
|
{
|
||||||
const ImVec2 backup_frame_padding = style.FramePadding;
|
const ImVec2 backup_frame_padding = style.FramePadding;
|
||||||
style.FramePadding.x = style.FramePadding.y;
|
style.FramePadding.x = style.FramePadding.y;
|
||||||
if (flags & ImGuiInputTextFlags_ReadOnly)
|
if (flags & ImGuiInputTextFlags_ReadOnly)
|
||||||
@ -4174,7 +4191,7 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
|
|||||||
char* dst = obj->TextA.Data + pos;
|
char* dst = obj->TextA.Data + pos;
|
||||||
char* src = obj->TextA.Data + pos + n;
|
char* src = obj->TextA.Data + pos + n;
|
||||||
memmove(dst, src, obj->TextLen - n - pos + 1);
|
memmove(dst, src, obj->TextLen - n - pos + 1);
|
||||||
obj->Edited = true;
|
obj->EditedBefore = obj->EditedThisFrame = true;
|
||||||
obj->TextLen -= n;
|
obj->TextLen -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4204,7 +4221,7 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha
|
|||||||
memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos));
|
memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos));
|
||||||
memcpy(text + pos, new_text, (size_t)new_text_len);
|
memcpy(text + pos, new_text, (size_t)new_text_len);
|
||||||
|
|
||||||
obj->Edited = true;
|
obj->EditedBefore = obj->EditedThisFrame = true;
|
||||||
obj->TextLen += new_text_len;
|
obj->TextLen += new_text_len;
|
||||||
obj->TextA[obj->TextLen] = '\0';
|
obj->TextA[obj->TextLen] = '\0';
|
||||||
|
|
||||||
@ -4406,6 +4423,7 @@ void ImGui::PopPasswordFont()
|
|||||||
// Return false to discard a character.
|
// Return false to discard a character.
|
||||||
static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* state, unsigned int* p_char, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard)
|
static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* state, unsigned int* p_char, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard)
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(state != NULL);
|
||||||
unsigned int c = *p_char;
|
unsigned int c = *p_char;
|
||||||
ImGuiInputTextFlags flags = state->Flags;
|
ImGuiInputTextFlags flags = state->Flags;
|
||||||
|
|
||||||
@ -4591,6 +4609,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
|
|||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
const char* s;
|
const char* s;
|
||||||
|
bool trailing_line_already_counted = false;
|
||||||
if (flags & ImGuiInputTextFlags_WordWrap)
|
if (flags & ImGuiInputTextFlags_WordWrap)
|
||||||
{
|
{
|
||||||
for (s = buf; s < buf_end; s = (*s == '\n') ? s + 1 : s)
|
for (s = buf; s < buf_end; s = (*s == '\n') ? s + 1 : s)
|
||||||
@ -4611,6 +4630,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Inactive path: we don't know buf_end ahead of time.
|
||||||
const char* s_eol;
|
const char* s_eol;
|
||||||
for (s = buf; ; s = s_eol + 1)
|
for (s = buf; ; s = s_eol + 1)
|
||||||
{
|
{
|
||||||
@ -4619,6 +4639,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
|
|||||||
if ((s_eol = strchr(s, '\n')) != NULL)
|
if ((s_eol = strchr(s, '\n')) != NULL)
|
||||||
continue;
|
continue;
|
||||||
s += strlen(s);
|
s += strlen(s);
|
||||||
|
trailing_line_already_counted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4629,11 +4650,8 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
|
|||||||
line_index->Offsets.push_back(0);
|
line_index->Offsets.push_back(0);
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
if (buf_end > buf && buf_end[-1] == '\n' && size <= max_output_buffer_size)
|
if (buf_end > buf && buf_end[-1] == '\n' && !trailing_line_already_counted && size++ <= max_output_buffer_size)
|
||||||
{
|
|
||||||
line_index->Offsets.push_back((int)(buf_end - buf));
|
line_index->Offsets.push_back((int)(buf_end - buf));
|
||||||
size++;
|
|
||||||
}
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4734,12 +4752,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
|
draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
|
||||||
draw_window->DC.CursorPos += style.FramePadding;
|
draw_window->DC.CursorPos += style.FramePadding;
|
||||||
inner_size.x -= draw_window->ScrollbarSizes.x;
|
inner_size.x -= draw_window->ScrollbarSizes.x;
|
||||||
|
|
||||||
|
// FIXME: Could this be a ImGuiChildFlags to affect the SetLastItemDataForWindow() call?
|
||||||
|
g.LastItemData.ID = id;
|
||||||
|
g.LastItemData.ItemFlags = item_data_backup.ItemFlags;
|
||||||
|
g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
|
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
|
||||||
ItemSize(total_bb, style.FramePadding.y);
|
ItemSize(total_bb, style.FramePadding.y);
|
||||||
if (!(flags & ImGuiInputTextFlags_MergedItem))
|
if (!(flags & ImGuiInputTextFlags_TempInput))
|
||||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -4770,11 +4793,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
if (is_wordwrap)
|
if (is_wordwrap)
|
||||||
wrap_width = ImMax(1.0f, GetContentRegionAvail().x + (draw_window->ScrollbarY ? 0.0f : -g.Style.ScrollbarSize));
|
wrap_width = ImMax(1.0f, GetContentRegionAvail().x + (draw_window->ScrollbarY ? 0.0f : -g.Style.ScrollbarSize));
|
||||||
|
|
||||||
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
|
|
||||||
|
|
||||||
const bool user_clicked = hovered && io.MouseClicked[0];
|
const bool user_clicked = hovered && io.MouseClicked[0];
|
||||||
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
|
const bool input_requested_by_nav = (g.ActiveId != id) && (g.NavActivateId == id);
|
||||||
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
|
const bool input_requested_by_reactivate = (g.InputTextReactivateId == id); // for io.ConfigInputTextEnterKeepActive
|
||||||
|
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput));
|
||||||
|
const ImGuiID scrollbar_id = (is_multiline && state != NULL) ? GetWindowScrollbarID(draw_window, ImGuiAxis_Y) : 0;
|
||||||
|
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == scrollbar_id;
|
||||||
|
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == scrollbar_id;
|
||||||
bool clear_active_id = false;
|
bool clear_active_id = false;
|
||||||
bool select_all = false;
|
bool select_all = false;
|
||||||
|
|
||||||
@ -4782,8 +4807,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
|
|
||||||
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
|
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
|
||||||
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
|
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
|
||||||
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
|
const bool init_make_active = (input_requested_by_user || input_requested_by_nav || input_requested_by_reactivate || user_scroll_finish);
|
||||||
const bool init_state = (init_make_active || user_scroll_active);
|
|
||||||
if (init_reload_from_user_buf)
|
if (init_reload_from_user_buf)
|
||||||
{
|
{
|
||||||
int new_len = (int)ImStrlen(buf);
|
int new_len = (int)ImStrlen(buf);
|
||||||
@ -4796,7 +4820,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
state->Stb->select_start = state->ReloadSelectionStart;
|
state->Stb->select_start = state->ReloadSelectionStart;
|
||||||
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
|
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
|
||||||
}
|
}
|
||||||
else if ((init_state && g.ActiveId != id) || init_changed_specs)
|
else if ((init_make_active && g.ActiveId != id) || init_changed_specs)
|
||||||
{
|
{
|
||||||
// Access state even if we don't own it yet.
|
// Access state even if we don't own it yet.
|
||||||
state = &g.InputTextState;
|
state = &g.InputTextState;
|
||||||
@ -4809,8 +4833,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
|
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
|
||||||
const int buf_len = (int)ImStrlen(buf);
|
const int buf_len = (int)ImStrlen(buf);
|
||||||
IM_ASSERT(((buf_len + 1 <= buf_size) || (buf_len == 0 && buf_size == 0)) && "Is your input buffer properly zero-terminated?");
|
IM_ASSERT(((buf_len + 1 <= buf_size) || (buf_len == 0 && buf_size == 0)) && "Is your input buffer properly zero-terminated?");
|
||||||
|
if (!user_scroll_finish)
|
||||||
|
{
|
||||||
state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
|
state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
|
||||||
memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
|
memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Preserve cursor position and undo/redo stack if we come back to same widget
|
// Preserve cursor position and undo/redo stack if we come back to same widget
|
||||||
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
|
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
|
||||||
@ -4821,6 +4848,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
// Start edition
|
// Start edition
|
||||||
state->ID = id;
|
state->ID = id;
|
||||||
state->TextLen = buf_len;
|
state->TextLen = buf_len;
|
||||||
|
state->EditedBefore = false;
|
||||||
if (!is_readonly)
|
if (!is_readonly)
|
||||||
{
|
{
|
||||||
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
|
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
|
||||||
@ -4906,7 +4934,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
|
|
||||||
// Release focus when we click outside
|
// Release focus when we click outside
|
||||||
if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560
|
if (g.ActiveId == id && io.MouseClicked[0] && !init_make_active) //-V560
|
||||||
clear_active_id = true;
|
clear_active_id = true;
|
||||||
|
|
||||||
// Lock the decision of whether we are going to take the path displaying the cursor or selection
|
// Lock the decision of whether we are going to take the path displaying the cursor or selection
|
||||||
@ -4936,7 +4964,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
{
|
{
|
||||||
IM_ASSERT(state != NULL);
|
IM_ASSERT(state != NULL);
|
||||||
state->Edited = false;
|
state->EditedThisFrame = false;
|
||||||
state->BufCapacity = buf_size;
|
state->BufCapacity = buf_size;
|
||||||
state->Flags = flags;
|
state->Flags = flags;
|
||||||
state->WrapWidth = wrap_width;
|
state->WrapWidth = wrap_width;
|
||||||
@ -5077,7 +5105,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
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 = Shortcut(ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiKey_KeypadEnter, f_repeat, id);
|
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_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_shift_enter = Shortcut(ImGuiMod_Shift | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_KeypadEnter, f_repeat, id);
|
||||||
|
const bool is_gamepad_validate = nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 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));
|
||||||
|
|
||||||
// FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of.
|
// FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of.
|
||||||
@ -5111,17 +5140,20 @@ 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 || is_ctrl_enter || is_gamepad_validate)
|
else if (is_enter || is_ctrl_enter || is_shift_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 != is_ctrl_enter))
|
bool is_new_line = is_multiline && !is_gamepad_validate && (is_shift_enter || (is_enter && !ctrl_enter_for_new_line) || (is_ctrl_enter && ctrl_enter_for_new_line));
|
||||||
|
if (!is_new_line)
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = clear_active_id = true;
|
||||||
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
||||||
|
{
|
||||||
|
// Queue reactivation, so that e.g. IsItemDeactivatedAfterEdit() will work. (#9001)
|
||||||
state->SelectAll(); // No need to scroll
|
state->SelectAll(); // No need to scroll
|
||||||
else
|
g.InputTextReactivateId = id; // Mark for reactivation on next frame
|
||||||
clear_active_id = true;
|
}
|
||||||
}
|
}
|
||||||
else if (!is_readonly)
|
else if (!is_readonly)
|
||||||
{
|
{
|
||||||
@ -5217,7 +5249,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process callbacks and apply result back to user's buffer.
|
// Process revert and user callbacks
|
||||||
const char* apply_new_text = NULL;
|
const char* apply_new_text = NULL;
|
||||||
int apply_new_text_length = 0;
|
int apply_new_text_length = 0;
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
@ -5247,18 +5279,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME-OPT: We always reapply the live buffer back to the input buffer before clearing ActiveId,
|
|
||||||
// even though strictly speaking it wasn't modified on this frame. Should mark dirty state from the stb_textedit callbacks.
|
|
||||||
// If we do that, need to ensure that as special case, 'validated == true' also writes back.
|
|
||||||
// This also allows the user to use InputText() without maintaining any user-side storage.
|
|
||||||
// (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object
|
|
||||||
// unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
|
|
||||||
const bool apply_edit_back_to_user_buffer = true;// !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
|
|
||||||
if (apply_edit_back_to_user_buffer)
|
|
||||||
{
|
|
||||||
// Apply current edited text immediately.
|
|
||||||
// Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
|
|
||||||
|
|
||||||
// User callback
|
// User callback
|
||||||
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
|
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
|
||||||
{
|
{
|
||||||
@ -5282,7 +5302,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
event_flag = ImGuiInputTextFlags_CallbackHistory;
|
event_flag = ImGuiInputTextFlags_CallbackHistory;
|
||||||
event_key = ImGuiKey_DownArrow;
|
event_key = ImGuiKey_DownArrow;
|
||||||
}
|
}
|
||||||
else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited)
|
else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->EditedThisFrame)
|
||||||
{
|
{
|
||||||
event_flag = ImGuiInputTextFlags_CallbackEdit;
|
event_flag = ImGuiInputTextFlags_CallbackEdit;
|
||||||
}
|
}
|
||||||
@ -5340,7 +5360,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will copy result string if modified
|
// Will copy result string if modified.
|
||||||
|
// FIXME-OPT: Could mark dirty state from the stb_textedit callbacks
|
||||||
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
|
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
|
||||||
{
|
{
|
||||||
apply_new_text = state->TextSrc;
|
apply_new_text = state->TextSrc;
|
||||||
@ -5348,9 +5369,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
|
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
|
||||||
|
// This is used when e.g. losing focus or tabbing out into another InputText() which may already be using the temp buffer.
|
||||||
if (g.InputTextDeactivatedState.ID == id)
|
if (g.InputTextDeactivatedState.ID == id)
|
||||||
{
|
{
|
||||||
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
|
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
|
||||||
@ -5363,12 +5384,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
g.InputTextDeactivatedState.ID = 0;
|
g.InputTextDeactivatedState.ID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
|
// Write back result to user buffer. This can currently only happen when (g.ActiveId == id) or when just deactivated.
|
||||||
|
// - As soon as the InputText() is active, our stored in-widget value gets priority over any underlying modification of the user buffer.
|
||||||
|
// - Make sure we always reapply the live buffer back to the input/user buffer before clearing ActiveId, even thought strictly speaking
|
||||||
|
// it was not modified on this frame. This allows the user to use InputText() without maintaining any user-side storage.
|
||||||
|
// (PS: if you use this property together with ImGuiInputTextFlags_CallbackResize, you are at the risk of recreating a temporary
|
||||||
|
// allocated/string object every frame. Which in the grand scheme of scheme is nothing, but isn't dear imgui vibe).
|
||||||
if (apply_new_text != NULL)
|
if (apply_new_text != NULL)
|
||||||
{
|
{
|
||||||
//// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
|
|
||||||
//// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
|
|
||||||
//// without any storage on user's side.
|
|
||||||
IM_ASSERT(apply_new_text_length >= 0);
|
IM_ASSERT(apply_new_text_length >= 0);
|
||||||
if (is_resizable)
|
if (is_resizable)
|
||||||
{
|
{
|
||||||
@ -5377,7 +5400,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
callback_data.ID = id;
|
callback_data.ID = id;
|
||||||
callback_data.Flags = flags;
|
callback_data.Flags = flags;
|
||||||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
|
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
|
||||||
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
|
callback_data.EventActivated = (state != NULL && g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
|
||||||
callback_data.Buf = buf;
|
callback_data.Buf = buf;
|
||||||
callback_data.BufTextLen = apply_new_text_length;
|
callback_data.BufTextLen = apply_new_text_length;
|
||||||
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
|
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
|
||||||
@ -5537,7 +5560,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
if (render_selection)
|
if (render_selection)
|
||||||
{
|
{
|
||||||
const ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
|
const ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
|
||||||
const float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
|
const float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME-DPI: those offsets should be part of the style? they don't play so well with multi-line selection.
|
||||||
const float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
|
const float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
|
||||||
const float bg_eol_width = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
const float bg_eol_width = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
||||||
|
|
||||||
@ -5566,7 +5589,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
rect.Min.y = draw_pos.y - draw_scroll.y + line_n * g.FontSize;
|
rect.Min.y = draw_pos.y - draw_scroll.y + line_n * g.FontSize;
|
||||||
rect.Max.x = rect.Min.x + rect_width;
|
rect.Max.x = rect.Min.x + rect_width;
|
||||||
rect.Max.y = rect.Min.y + bg_offy_dn + g.FontSize;
|
rect.Max.y = rect.Min.y + bg_offy_dn + g.FontSize;
|
||||||
rect.Min.y -= bg_offy_up;
|
rect.Min.y += bg_offy_up;
|
||||||
rect.ClipWith(clip_rect);
|
rect.ClipWith(clip_rect);
|
||||||
draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
|
draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
|
||||||
}
|
}
|
||||||
@ -5574,7 +5597,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find render position for right alignment (single-line only)
|
// Find render position for right alignment (single-line only)
|
||||||
if (g.ActiveId != id && flags & ImGuiInputTextFlags_ElideLeft)
|
if (g.ActiveId != id && (flags & ImGuiInputTextFlags_ElideLeft) && !render_cursor && !render_selection)
|
||||||
draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display, NULL).x - style.FramePadding.x);
|
draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display, NULL).x - style.FramePadding.x);
|
||||||
//draw_scroll.x = state->Scroll.x; // Preserve scroll when inactive?
|
//draw_scroll.x = state->Scroll.x; // Preserve scroll when inactive?
|
||||||
|
|
||||||
@ -5595,7 +5618,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
|
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
||||||
|
|
||||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||||
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||||
@ -6453,7 +6476,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
|||||||
if (g.Style.FrameBorderSize > 0.0f)
|
if (g.Style.FrameBorderSize > 0.0f)
|
||||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||||
else
|
else
|
||||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border // FIXME-DPI
|
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 0, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drag and Drop Source
|
// Drag and Drop Source
|
||||||
@ -6733,6 +6756,8 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char
|
|||||||
return TreeNodeBehavior(id, flags, label, label_end);
|
return TreeNodeBehavior(id, flags, label, label_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The reason those two functions are not yet in public API is because I would like to design a more feature-full and generic API for this.
|
||||||
|
// They are otherwise function (cc: #3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
|
||||||
bool ImGui::TreeNodeGetOpen(ImGuiID storage_id)
|
bool ImGui::TreeNodeGetOpen(ImGuiID storage_id)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -6740,15 +6765,16 @@ bool ImGui::TreeNodeGetOpen(ImGuiID storage_id)
|
|||||||
return storage->GetInt(storage_id, 0) != 0;
|
return storage->GetInt(storage_id, 0) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::TreeNodeSetOpen(ImGuiID storage_id, bool open)
|
void ImGui::TreeNodeSetOpen(ImGuiID storage_id, bool is_open)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage;
|
ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage;
|
||||||
storage->SetInt(storage_id, open ? 1 : 0);
|
storage->SetInt(storage_id, is_open ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
|
bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
|
||||||
{
|
{
|
||||||
|
// Leaf node always open a new tree/id scope. If you never use it, add ImGuiTreeNodeFlags_NoTreePushOnOpen.
|
||||||
if (flags & ImGuiTreeNodeFlags_Leaf)
|
if (flags & ImGuiTreeNodeFlags_Leaf)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -8172,10 +8198,13 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
|
|||||||
{
|
{
|
||||||
ImGuiButtonFlags button_flags = *p_button_flags;
|
ImGuiButtonFlags button_flags = *p_button_flags;
|
||||||
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
|
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
|
||||||
if ((!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) && !(ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease))
|
button_flags &= ~(ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease);
|
||||||
button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease;
|
if (ms->Flags & ImGuiMultiSelectFlags_SelectOnClickAlways)
|
||||||
else
|
button_flags |= ImGuiButtonFlags_PressedOnClick;
|
||||||
|
else if (ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease)
|
||||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||||
|
else // ImGuiMultiSelectFlags_SelectOnAuto
|
||||||
|
button_flags |= (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) ? ImGuiButtonFlags_PressedOnClick : ImGuiButtonFlags_PressedOnClickRelease;
|
||||||
*p_button_flags = button_flags;
|
*p_button_flags = button_flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8295,7 +8324,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|||||||
// Box-select
|
// Box-select
|
||||||
ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
|
ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
|
||||||
if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||||
if (selected == false && !g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
|
if (!g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
|
||||||
BoxSelectPreStartDrag(ms->BoxSelectId, item_data);
|
BoxSelectPreStartDrag(ms->BoxSelectId, item_data);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
@ -9244,11 +9273,12 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
PushID(label);
|
PushID(label);
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
BeginDisabled();
|
BeginDisabled();
|
||||||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
|
||||||
bool pressed;
|
bool pressed;
|
||||||
|
|
||||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups;
|
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups;
|
||||||
|
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||||
{
|
{
|
||||||
// Menu inside a horizontal menu bar
|
// Menu inside a horizontal menu bar
|
||||||
@ -9256,9 +9286,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
|
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
|
||||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
|
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
|
||||||
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
|
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
|
||||||
float w = label_size.x;
|
|
||||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset);
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
|
pressed = Selectable("", menu_is_open, selectable_flags, label_size);
|
||||||
LogSetNextTextDecoration("[", "]");
|
LogSetNextTextDecoration("[", "]");
|
||||||
RenderText(text_pos, label);
|
RenderText(text_pos, label);
|
||||||
PopStyleVar();
|
PopStyleVar();
|
||||||
@ -9272,7 +9301,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
|
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
|
||||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||||
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
||||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
float min_w = offsets->DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
||||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||||
ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||||
@ -9457,17 +9486,16 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
BeginDisabled();
|
BeginDisabled();
|
||||||
|
|
||||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
|
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||||
{
|
{
|
||||||
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
|
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
|
||||||
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
|
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
|
||||||
float w = label_size.x;
|
|
||||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
|
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
|
||||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
|
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
|
||||||
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
|
pressed = Selectable("", selected, selectable_flags, ImVec2(label_size.x, 0.0f));
|
||||||
PopStyleVar();
|
PopStyleVar();
|
||||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
||||||
RenderText(text_pos, label);
|
RenderText(text_pos, label);
|
||||||
@ -9481,7 +9509,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||||
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
|
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
|
||||||
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
||||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
||||||
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||||
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||||
@ -10603,7 +10631,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Click to Select a tab
|
// Click to Select a tab
|
||||||
ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap);
|
ImGuiButtonFlags button_flags = ((ImGuiButtonFlags)(is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap);
|
||||||
if (g.DragDropActive && !g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW)) // FIXME: May be an opt-in property of the payload to disable this
|
if (g.DragDropActive && !g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW)) // FIXME: May be an opt-in property of the payload to disable this
|
||||||
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
|
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
|
||||||
bool hovered, held, pressed;
|
bool hovered, held, pressed;
|
||||||
|
|||||||
@ -315,7 +315,7 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0
|
|||||||
if (node->y > min_y) {
|
if (node->y > min_y) {
|
||||||
// raise min_y higher.
|
// raise min_y higher.
|
||||||
// we've accounted for all waste up to min_y,
|
// we've accounted for all waste up to min_y,
|
||||||
// but we'll now add more waste for everything we've visted
|
// but we'll now add more waste for everything we've visited
|
||||||
waste_area += visited_width * (node->y - min_y);
|
waste_area += visited_width * (node->y - min_y);
|
||||||
min_y = node->y;
|
min_y = node->y;
|
||||||
// the first time through, visited_width might be reduced
|
// the first time through, visited_width might be reduced
|
||||||
@ -470,7 +470,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
|||||||
|
|
||||||
// insert the new node into the right starting point, and
|
// insert the new node into the right starting point, and
|
||||||
// let 'cur' point to the remaining nodes needing to be
|
// let 'cur' point to the remaining nodes needing to be
|
||||||
// stiched back in
|
// stitched back in
|
||||||
|
|
||||||
cur = *res.prev_link;
|
cur = *res.prev_link;
|
||||||
if (cur->x < res.x) {
|
if (cur->x < res.x) {
|
||||||
|
|||||||
@ -886,7 +886,7 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, fl
|
|||||||
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
|
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
|
||||||
|
|
||||||
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
|
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
|
||||||
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
|
// the same as stbtt_GetCodepointBitmap, but you can specify a subpixel
|
||||||
// shift for the character
|
// shift for the character
|
||||||
|
|
||||||
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
|
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user