Merge branch 'ocornut:master' into imgui_impl_emscripten

This commit is contained in:
slowriot 2026-09-07 22:38:05 +01:00 • committed by GitHub
commit aaa8b8f4cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 194 additions and 74 deletions

View file

@ -16,6 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
@ -106,8 +107,8 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
// Setup viewport
D3D10_VIEWPORT vp = {};
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;

View file

@ -110,8 +110,8 @@ static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11D
// Setup viewport
D3D11_VIEWPORT vp = {};
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x;
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y;
vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;

View file

@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-05: DirectX12: *BREAKING CHANGE* Removed support for legacy `ImGui_ImplDX12_Init()` signature obsoleted in 1.91.6 (2024-11-15) because it needed to forcefully disable support for ImGuiBackendFlags_RendererHasTextures. (#9487)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
@ -183,8 +184,8 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
// Setup viewport
D3D12_VIEWPORT vp = {};
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x;
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y;
vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0.0f;

View file

@ -16,6 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
@ -163,8 +164,8 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
{
.originX = 0.0,
.originY = 0.0,
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x),
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y),
.width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
.height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
.znear = 0.0,
.zfar = 1.0
};
@ -203,8 +204,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
MetalContext* ctx = bd->SharedMetalContext;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return;

View file

@ -19,6 +19,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-07: Metal 4: Added metal-cpp support. (#9461)
// 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458)
@ -162,8 +163,8 @@ static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4Comm
{
.originX = 0.0,
.originY = 0.0,
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x),
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y),
.width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
.height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
.znear = 0.0,
.zfar = 1.0
};
@ -203,8 +204,8 @@ void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id<MTL4CommandBuffer
MetalContext* ctx = bd->SharedMetalContext;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return;

View file

@ -26,6 +26,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
@ -168,8 +169,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width == 0 || fb_height == 0)
return;

View file

@ -23,6 +23,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
// 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering.
// 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577)
@ -455,8 +456,8 @@ static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*,
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0)
return;

View file

@ -22,6 +22,7 @@
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
// CHANGELOG
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
// 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)
@ -163,8 +164,8 @@ static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer*
void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0)
return;
@ -229,8 +230,8 @@ static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*,
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0)
return;

View file

@ -27,6 +27,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-09-03: Added for support for multiple Vulkan contexts with custom loaders. (#6616)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
// 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.
@ -587,8 +588,8 @@ void ImGui_ImplVulkan_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImD
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0)
return;

View file

@ -20,6 +20,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-31: Update to compile with wgpu-native 29.0. (#9377, #9532, #9530)
// 2026-08-18: Fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport() when FramebufferScale is >1.0f. (#9515, #8628)
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
@ -436,8 +437,8 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
}
// Setup viewport
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, (float)fb_width, (float)fb_height, 0, 1);
// Bind shader and vertex buffers
@ -460,8 +461,8 @@ static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, con
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
{
// Avoid rendering when minimized
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
return;

View file

@ -42,9 +42,9 @@ HOW TO UPDATE?
Breaking Changes:
- Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in
favor of `style.CurveTesselationMaxError` (default 1.12)` which is in Pixels unit. It is
favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit. It is
easier to tweak + this allows us to easily scale error threshold on high density screens.
- style.CurveTesselationMaxError == sqrf(style.CurveTessellationTol).
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
- Backends:
- DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was
obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support
@ -55,8 +55,8 @@ Other Changes:
- Drags, Sliders:
- Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
- Ongoing drags may be cancelled using Escape or Gamepad Triangle, reverting
to the initial value. (#8564, #9534)
- Ongoing drags may be cancelled using Right-Click, Escape or Gamepad Triangle.
Cancelling reverts to the initial value. (#8564, #9534)
- TreeNode:
- Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
features or other features requiring stack storage. (#9509) [@lasrod]
@ -69,7 +69,15 @@ Other Changes:
disabled color buttons have the same color as non-disabled oness. (#9511)
- ColorButton: fixed issues/inconsistencies with checkerboard rendering when combining
color alpha and global style alpha. (#9511) [@enjmiah, @ocornut]
- Popups:
- Amended context menu right-click opening code to check that the right-click
hasn't been owned by another items. This is more correct and also necessary
to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
- Misc:
- Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values.
Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX()
and Combo() functions.
The scoped flag is designed for usage by advanced property editors. (#5518, #5677, #6865)
- Fixed `GetBackgroundDrawList()`/`GetForegroundDrawList()` not being properly reset
every frame when cumulated session time is very large (e.g. a few days). [@lailoken]
- Added `IM_NODEBUGSTEP` helper to tag functions with `__declspec(non_user_code)` (MSVC)
@ -77,6 +85,8 @@ Other Changes:
trivial functions when stepping into.
- Tagged various trivial functions using `IM_NODEBUGSTEP`: `ImVec2()`, `ImVec4()` etc.
and various operators.
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing
issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
- ImDrawList:
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
- AA Fringe is scaled accordingly.
@ -84,6 +94,8 @@ Other Changes:
- Reworked assert in PushTexture() to allow convenience grace period of using a
texture that was queue for destroy during the frame. Make it safe to stick to
an existing texture during the frame. (#9528, #8465)
- Demo:
- Added `Widgets->Mixed Values` section. (#5518, #5677, #6865)
- Backends:
- QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry]
- SDL2: fixed querying framebuffer scale/density when using Metal without

View file

@ -131,8 +131,8 @@
ImDrawData* draw_data = ImGui::GetDrawData();
[[self openGLContext] makeCurrentContext];
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
glViewport(0, 0, width, height);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);

View file

@ -131,8 +131,8 @@
ImDrawData* draw_data = ImGui::GetDrawData();
[[self openGLContext] makeCurrentContext];
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
glViewport(0, 0, width, height);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);

View file

@ -395,8 +395,8 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTesselationMaxError` (default 1.12)` which is in Pixels unit.
- style.CurveTesselationMaxError == sqrf(style.CurveTessellationTol).
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit.
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
- 2026/07/20 (1.92.9) - DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now defaulting to being disabled:
inputting a value with the keyboard doesn't write intermediate values to backing variable. (#9476)
- Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123.
@ -1387,10 +1387,9 @@ static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
// Platform Dependents default implementation for ImGuiPlatformIO functions
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io);
static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx);
static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text);
static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data);
static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path);
namespace ImGui
{
@ -1573,7 +1572,7 @@ ImGuiStyle::ImGuiStyle()
DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
// Rendering & Tesselation
// Rendering & Tessellation
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
@ -4381,6 +4380,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
MouseCursor = ImGuiMouseCursor_Arrow;
MouseStationaryTimer = 0.0f;
MixedValueLabel = "-";
InputTextPasswordFontBackupFlags = ImFontFlags_None;
InputTextReactivateId = 0;
TempInputId = 0;
@ -4486,10 +4486,7 @@ void ImGui::Initialize()
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_COUNTOF(GLocalizationEntriesEnUS));
// Setup default ImGuiPlatformIO clipboard/IME handlers.
g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
InitializeDefaultPlatformHandlers(g.PlatformIO);
// Setup session starting date
#ifndef IMGUI_DISABLE_TIME_FUNCTIONS
@ -12796,7 +12793,7 @@ bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (IsMouseReleased(mouse_button, id) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
return true;
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
return true;
@ -12807,7 +12804,7 @@ bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (IsMouseReleased(mouse_button, ImGuiKeyOwner_NoOwner) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
return true;
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
@ -12878,9 +12875,9 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flag
ImGuiWindow* window = g.CurrentWindow;
if (!str_id)
str_id = "void_context";
ImGuiID id = window->GetID(str_id);
ImGuiID id = window->GetID(str_id); // FIXME: Use a global ID?
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
if (IsMouseReleased(mouse_button, id) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
if (GetTopMostPopupModal() == NULL)
OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
@ -16101,6 +16098,7 @@ void ImGuiPlatformIO::ClearPlatformHandlers()
Platform_OpenInShellUserData = NULL;
Platform_SetImeDataFn = NULL;
Platform_ImeUserData = NULL;
InitializeDefaultPlatformHandlers(*this); // Rrevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation.
}
void ImGuiPlatformIO::ClearRendererHandlers()
@ -16413,6 +16411,15 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImG
#endif // Default IME handlers
// Setup default ImGuiPlatformIO clipboard/IME handlers
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io)
{
platform_io.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl;
platform_io.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
platform_io.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
}
//-----------------------------------------------------------------------------
// [SECTION] METRICS/DEBUGGER WINDOW
//-----------------------------------------------------------------------------

View file

@ -30,7 +30,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.93.0 WIP"
#define IMGUI_VERSION_NUM 19295
#define IMGUI_VERSION_NUM 19296
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@ -1258,6 +1258,7 @@ enum ImGuiItemFlags_
ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window.
ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
ImGuiItemFlags_Disabled = 1 << 6, // false // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags().
ImGuiItemFlags_MixedValue = 1 << 9, // false // [BETA] Represent a mixed/indeterminate value. Replace value label with "-" and apply edits on validation. Only supported by some widgets: Checkbox, RadioButton, Sliders and Drags.
//---------------------------------------------------------------------------------
// LiveEdit refers to applying edits to backing variables _while_ typing a value using the keyboard.
@ -2384,7 +2385,7 @@ struct ImGuiStyle
ImVec2 DisplaySafeAreaPadding; // Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later.
// Rendering & Tesselation
// Rendering & Tessellation
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).

View file

@ -87,6 +87,7 @@ Index of this file:
// [SECTION] DemoWindowWidgetsImages()
// [SECTION] DemoWindowWidgetsListBoxes()
// [SECTION] DemoWindowWidgetsLiveEdit()
// [SECTION] DemoWindowWidgetsMixedValues()
// [SECTION] DemoWindowWidgetsMultiComponents()
// [SECTION] DemoWindowWidgetsPlotting()
// [SECTION] DemoWindowWidgetsProgressBars()
@ -2020,7 +2021,7 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
{
if (ImGui::TreeNode("Live Edit Flags"))
{
IMGUI_DEMO_MARKER("Widgets/Live Edit Flgs");
IMGUI_DEMO_MARKER("Widgets/Live Edit Flags");
ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing.");
@ -2050,6 +2051,61 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
}
}
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsMixedValues()
//-----------------------------------------------------------------------------
static void DemoWindowWidgetsMixedValues()
{
if (ImGui::TreeNode("Mixed Values"))
{
// This is designed for advanced property editors which are generally reusable and data-driven.
HelpMarker("Using ImGuiItemFlags_MixedValue.");
static float items[3] = { 12.0f, 0.0f, 0.0f };
float* item_ref = &items[0];
ImGui::SeparatorText("Scalar/Text Widgets");
const bool is_mixed = memcmp(&items[0], &items[1], sizeof(float)) != 0 || memcmp(&items[0], &items[2], sizeof(float)) != 0;
// Demonstrate Drags, Sliders, Inputs
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, is_mixed);
bool edited = false;
edited |= ImGui::DragFloat("DragFloat", item_ref);
edited |= ImGui::SliderFloat("SliderFloat", item_ref, 0.0f, 100.0f);
edited |= ImGui::InputFloat("InputFloat", item_ref, 1.0f);
if (edited)
for (float& item : items)
if (&item != item_ref)
item = *item_ref;
ImGui::PopItemFlag();
ImGui::Text("Underlying data:");
ImGui::InputFloat("item 0 (ref)", &items[0]);
ImGui::InputFloat("item 1", &items[1]);
ImGui::InputFloat("item 2", &items[2]);
// Demonstrate Checkbox(), RadioButton(), Combo(), ColorEdit4()
ImGui::SeparatorText("Others Widgets");
ImGui::Text("(note: edits are not applied in this demo)"); // <-- Would need more state tracking.
bool b_on = true, b_off = false;
ImGui::Checkbox("Checkbox On", &b_on);
ImGui::Checkbox("Checkbox Off", &b_off);
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
ImGui::Checkbox("Checkbox Mixed", &b_off);
ImGui::RadioButton("RadioButton Mixed", true);
ImGui::SameLine();
ImGui::RadioButton("RadioButton Mixed##2", true); // Showing 2 radio buttons makes the example more clear
int combo_idx = 0;
ImGui::Combo("Combo", &combo_idx, "One\0Two\0Three\0");
ImVec4 color(0.5f, 0.5f, 0.5f, 0.5f);
ImGui::ColorEdit4("ColorEdit4", &color.x);
ImGui::PopItemFlag();
ImGui::TreePop();
}
}
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsMultiComponents()
//-----------------------------------------------------------------------------
@ -2230,12 +2286,14 @@ static void DemoWindowWidgetsQueryingStatuses()
};
static int item_type = 4;
static bool item_disabled = false;
static bool item_mixedvalue = false;
static bool liveedit_flags_override = false;
static ImGuiItemFlags liveedit_flags = 0;
ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
ImGui::SameLine();
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
ImGui::Checkbox("Item Disabled", &item_disabled);
ImGui::Checkbox("Item MixedValue", &item_mixedvalue);
ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override);
ImGui::SameLine();
if (!liveedit_flags_override)
@ -2260,6 +2318,8 @@ static void DemoWindowWidgetsQueryingStatuses()
static char str[16] = {};
if (item_disabled)
ImGui::BeginDisabled(true);
if (item_mixedvalue)
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
@ -2343,6 +2403,8 @@ static void DemoWindowWidgetsQueryingStatuses()
ImGui::PopItemFlag();
ImGui::PopItemFlag();
}
if (item_mixedvalue)
ImGui::PopItemFlag();
if (item_disabled)
ImGui::EndDisabled();
@ -4505,6 +4567,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
DemoWindowWidgetsImages();
DemoWindowWidgetsListBoxes();
DemoWindowWidgetsLiveEdit(demo_data);
DemoWindowWidgetsMixedValues();
DemoWindowWidgetsMultiComponents();
DemoWindowWidgetsPlotting();
DemoWindowWidgetsProgressBars();

View file

@ -993,7 +993,6 @@ enum ImGuiItemFlagsPrivate_
{
// Controlled by user
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
@ -2305,6 +2304,7 @@ struct ImGuiContext
ImVec2 WheelingAxisAvg;
// Item/widgets state and tracking information
const char* MixedValueLabel; // Value replacement when displaying a mixed value. Default to "-" (Unreal uses "Multiple values", Unity uses "---"). May be interpreted as a format: must not contain single %.
ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier
ImGuiID DebugHookIdInfoId; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
ImGuiID HoveredId; // Hovered widget, filled during the frame

View file

@ -1398,7 +1398,7 @@ bool ImGui::RadioButton(const char* label, bool active)
RenderNavCursor(total_bb, id);
const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
if (active)
if (active && (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) == 0)
{
const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f));
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
@ -2176,7 +2176,9 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo
// Call the getter to obtain the preview string which is a parameter to BeginCombo()
const char* preview_value = NULL;
if (*current_item >= 0 && *current_item < items_count)
if ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_MixedValue)
preview_value = "";
else if (*current_item >= 0 && *current_item < items_count)
preview_value = getter(user_data, *current_item);
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
@ -2665,10 +2667,10 @@ static bool ShortcutsForCancel(ImGuiID id)
ImGuiContext& g = *GImGui;
bool is_cancel_with_keyboard = ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_None, id);
bool is_cancel_with_gamepad = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0 && ImGui::Shortcut(ImGuiKey_NavGamepadCancel, ImGuiInputFlags_None, id);
//bool is_cancel_with_mouse = ImGui::IsMouseClicked(ImGuiMouseButton_Right, ImGuiInputFlags_None, id);
//if (is_cancel_with_mouse)
// ImGui::SetKeyOwner(ImGuiKey_MouseRight, id);
return is_cancel_with_keyboard || is_cancel_with_gamepad; //|| is_cancel_with_mouse
bool is_cancel_with_mouse = ImGui::IsMouseReleased(ImGuiMouseButton_Right, id);
if (is_cancel_with_mouse)
ImGui::SetKeyOwner(ImGuiKey_MouseRight, id);
return is_cancel_with_keyboard || is_cancel_with_gamepad || is_cancel_with_mouse;
}
bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
@ -2815,8 +2817,9 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
MarkItemEdited(id);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
const char* format_for_display = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) ? g.MixedValueLabel : format;
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format_for_display);
if (g.LogEnabled)
LogSetNextTextDecoration("{", "}");
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
@ -3422,8 +3425,9 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
const char* format_for_display = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) ? g.MixedValueLabel : format;
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format_for_display);
if (g.LogEnabled)
LogSetNextTextDecoration("{", "}");
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
@ -3576,8 +3580,9 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
// For the vertical slider we allow centered text to overlap the frame padding
const char* format_for_display = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) ? g.MixedValueLabel : format;
char value_buf[64];
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format_for_display);
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
@ -3815,7 +3820,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
// Only mark as edited if new value is different
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0 || (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue);
if (value_changed)
MarkItemEdited(id);
return value_changed;
@ -3892,6 +3897,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
}
}
if (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue)
value_changed |= ret;
// Step buttons
if (has_step_buttons)
@ -4857,6 +4864,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
if (is_resizable)
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
@ -4943,7 +4951,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!is_multiline)
{
if (flags & ImGuiInputTextFlags_AutoSelectAll)
if ((flags & ImGuiInputTextFlags_AutoSelectAll) || is_mixed)
select_all = true;
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
select_all = true;
@ -5021,7 +5029,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Select the buffer to render.
const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
// Password pushes a temporary font with only a fallback glyph
if (is_password && !is_displaying_hint)
@ -5448,7 +5456,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText)
{
// Apply when modified
if (strcmp(state->TextSrc, buf) != 0)
if (strcmp(state->TextSrc, buf) != 0 || (is_mixed && validated))
{
apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen;
@ -5458,7 +5466,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else
{
// Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert)
value_changed = ((validated || clear_active_id || revert_edit) && strcmp(state->TextSrc, buf) != 0);
value_changed = (validated || clear_active_id || revert_edit) && (strcmp(state->TextSrc, buf) != 0 || (is_mixed && validated));
apply_new_text = value_changed ? state->TextSrc : NULL;
apply_new_text_length = value_changed ? state->TextLen : 0;
}
@ -5543,7 +5551,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Display hint when contents is empty
// At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368)
const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
if (new_is_displaying_hint != is_displaying_hint)
{
if (is_password && !is_displaying_hint)
@ -5552,10 +5560,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_password && !is_displaying_hint)
PushPasswordFont();
}
if (is_displaying_hint)
if (is_mixed && g.ActiveId != id && apply_new_text == NULL)
{
buf_display = g.MixedValueLabel;
buf_display_end = buf_display + strlen(g.MixedValueLabel);
render_cursor = render_selection = false;
}
else if (is_displaying_hint)
{
buf_display = hint;
buf_display_end = hint + ImStrlen(hint);
buf_display_end = buf_display + ImStrlen(buf_display);
}
else
{
@ -6044,7 +6058,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
PushItemFlag(ImGuiItemFlags_MixedValue, false);
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
PopItemFlag();
}
EndPopup();
}
@ -6319,6 +6335,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
if (!(flags & ImGuiColorEditFlags_NoSidePreview))
{
PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
if ((flags & ImGuiColorEditFlags_NoLabel))
Text("Current");
@ -6336,6 +6353,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
}
}
PopItemFlag();
PopItemFlag();
EndGroup();
}
@ -6554,14 +6572,20 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (flags & ImGuiColorEditFlags_InputHSV)
ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
float grid_step = ImMin(size.x, size.y) / 2.99f;
float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
const ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
const float grid_step = ImMin(size.x, size.y) / 2.99f;
const float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
const float backup_alpha = g.Style.Alpha;
if (g.DisabledStackSize > 0)
g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
if (is_mixed)
{
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding);
RenderTextClipped(ImVec2(bb.Min.x, bb.Min.y + g.Style.FramePadding.y), bb.Max, g.MixedValueLabel, NULL, NULL, ImVec2(0.5f, 0.0f));
}
else if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
{
float mid_x = IM_ROUND((bb.Min.x + bb.Max.x) * 0.5f);
if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
@ -6598,7 +6622,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
else
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ColorButton(desc_id, col, flags);
PopItemFlag();
SameLine();
TextEx("Color");
EndDragDropSource();
@ -6642,7 +6668,9 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_;
PushItemFlag(ImGuiItemFlags_MixedValue, false);
ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz);
PopItemFlag();
SameLine();
if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_))
{