Compare commits

..

30 Commits

Author SHA1 Message Date
ocornut
201b7e8022 Demo: added variety of usage scenarios, hooking Alt, Mouse Wheel, Home, CTRL+Tab demos.
(relate to issues: 456, 2637, 2620, 2891, 3370, 3724, 4828, 5108, 5242, 5641)
Amend 2026/05/07 for SetItemKeyOwner() returning a boolean.
2026-05-12 16:52:32 +02:00
ocornut
ba331feb28 Demo: added SetKeyOwner(), ImGuiInputFlags_LockThisFrame, ImGuiInputFlags_LockUntilRelease demo.
(relate to issues: 456, 2637, 2620, 2891, 3370, 3724, 4828, 5108, 5242, 5641)
2026-05-12 16:52:32 +02:00
ocornut
8936b58fe2 Version 1.92.8
Include minor bits: adjust activeid logging, tweak comments.
2026-05-12 16:30:30 +02:00
omar
eebaddd340 Docs: added SECURITY.md. 2026-05-11 19:03:08 +02:00
ocornut
73afb6b6e6 Fonts: clarify that ClearFonts() be useful over calling Clear(). 2026-05-11 17:45:59 +02:00
ocornut
b8f6c51af7 Fonts: move ClearFonts(), ClearInputData(), ClearTexData() implementation (no other changes) 2026-05-11 17:42:08 +02:00
ocornut
4ac473b2c7 Fixed BeginMenu() leading to window with is_resizable_width=true. Fix/amend 95bd1577d + ac1f57b. (#9355) 2026-05-11 16:35:40 +02:00
ocornut
ac1f57ba0c Fixed BeginMenu() leading to window with is_resizable_width=true. Fix/amend 95bd1577d. (#9355)
We should instead probably make BeginChild() not set on ImGuiWindowFlags_AlwaysAutoResize on either ResizeX or ResizeY, but that'll be done later.
2026-05-11 16:34:33 +02:00
ocornut
821a396556 Fixed warning on Clang 26. 2026-05-11 15:59:42 +02:00
manuel
2b31f65167 Examples: WebGPU+GLFW/SDL2/SDL3: wire up the IMGUI_WGVK_DIR path. (#9387)
The block was a stub - find Vulkan, detect Wayland/X11, set the SUPPORT_*_SURFACE defines that wgvk.c needs.
2026-05-11 15:42:16 +02:00
manuel
b58836f287 Backends: WebGPU: detect WGSL support at runtime instead of excluding WGVK at compile time. (#9387)
Previously WGVK was hard-disabled from WGSL via #if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK),
forcing the SPIRV fallback unconditionally. Now the WGSL path is attempted on all backends
and an empty stage_desc is returned when the module fails to compile letting the existing
SPIRV fallback at the call site kick in.
2026-05-11 15:38:27 +02:00
ocornut
bca5a69928 BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when opening a menu inside a small host window forcing the child menu window to be repositioned under the mouse cursor. (#8233, #9394)
nb: ImGuiSelectableFlags_NoHoldingActiveID is not used anymore. Would remove remove once we remove the unnecessary call to Selectable() from MenuItem().
2026-05-11 15:32:39 +02:00
ocornut
eb453f2be6 Checkbox, Style: added ImGuiCol_CheckboxSelectedBg. (#9392) 2026-05-11 14:30:34 +02:00
ocornut
56b37bf93c Inputs: SetItemKeyOwner(): does not set ownership is key is already taken.
(#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
2026-05-07 21:22:33 +02:00
ocornut
0eae77f783 Inputs: SetItemKeyOwner(): return true if ownership has been requested, which can to be checked to accurately gate further input test.
(#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
2026-05-07 21:15:27 +02:00
ocornut
02ccd9f348 Scrolling, Inputs: using mouse wheel to scroll takes and keeps ownership of the corresponding keys while a wheeling window is locked.
Ref 4448d975d. (#2604, #3795)
2026-05-07 20:51:57 +02:00
ocornut
163b8670c8 Demo: added image viewer with magnifier and grid. 2026-05-07 20:20:05 +02:00
ocornut
a70b97ee48 Warning fixes. 2026-05-07 16:51:34 +02:00
ocornut
6df50a0667 (Breaking) DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke(). thickness<>flags.
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
The aim is to be able to use/add flags to more ImDrawList functions, and making existing functions consistents was deemed very desirable.
2026-05-07 16:37:57 +02:00
ocornut
976c5c0f3a Textures: extract ImTextureDataQueueUpload() out of ImFontAtlasTextureBlockQueueUpload() (#8465)
Not atlas specific, in support of texture system.
2026-05-06 16:19:39 +02:00
Mikko Mononen
691b89baae ImDrawList: added AddLineH(), AddLineV() helpers. (#9360)
This commit is aimed to be a lossless transform. Further layout fixes in subsequent commits.
2026-04-28 17:04:54 +02:00
ocornut
c0b693b1d4 MultiSelect: Box-Select + Tables: fixed when using SpanAllColumns paths. (#9383, #7994)
Amend d1a8995 which didn't fix the thing it claimed to fix, as my naive last minute refactor broke it.
2026-04-28 15:58:21 +02:00
Alexander "FireFox" Ong
865a6dfa59 InputScalar: fixed not parsing user input when the display format is configured not to show the scalar value. (#9385)
Useful e.g. for displaying "mixed" inputs, where a single field might represent multiple different values.
2026-04-28 15:25:12 +02:00
Vlad
dee9b15bbe Backends: Metal: add sampler states and DrawCallback_SetSamplerLinear / DrawCallback_SetSamplerNearest callbacks. (#9381, #9371, #9378) 2026-04-28 15:09:23 +02:00
ocornut
d1a8995634 MultiSelect: Box-Select + Tables: fixed when using SpanAllColumns paths. (#9383, #7994)
Amend ac88294 + d7b40ab
2026-04-28 14:58:47 +02:00
ocornut
ab36fbaf48 Drag and Drop, Style: added ImGuiStyleVar_DragDropTargetRounding. (#9056)
+ readded rounding arg to RenderDragDropTargetRectEx().
2026-04-27 18:23:56 +02:00
ocornut
e3033c3975 Examples: moving example_win32_directx11 on top of the .sln makes it the default selected project. 2026-04-24 17:38:51 +02:00
ocornut
10c378cdfc InputInt, InputFloat, InputScalar: reinstated and fixed ImGuiInputTextFlags_EnterReturnsTrue. (#8665, #9299, #8065, #3946, #6284, #9117) 2026-04-24 15:15:19 +02:00
ocornut
db23a78c60 Internals: store ImGuiItemStatusFlags_EditedInternal bypassing ImGuiItemFlags_NoMarkEdited.
Convenient if the same signal is not passed via e.g. return value. (#8665, #9299, #8065, #3946, #6284, #9117)
2026-04-24 15:15:16 +02:00
ocornut
bda49826cf Backends: OpenGL3: build fix for WebGL/ES2/Emscripten. (#9378)
Amend 6b05f71 which was incorrectly labelled.
2026-04-24 12:26:21 +02:00
19 changed files with 1031 additions and 584 deletions

View File

@@ -5,8 +5,6 @@
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.

View File

@@ -5,8 +5,6 @@
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest callbacks.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -18,6 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 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)
// 2026-04-03: Metal: avoid redundant vertex buffer bind in SetupRenderState. (#9343)
@@ -79,6 +78,8 @@
@interface MetalContext : NSObject
@property (nonatomic, strong) id<MTLDevice> device;
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor; // framebuffer descriptor for current frame; transient
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
@property (nonatomic, strong) NSMutableArray<MetalBuffer*>* bufferCache;
@@ -91,6 +92,7 @@
struct ImGui_ImplMetal_Data
{
MetalContext* SharedMetalContext;
id<MTLRenderCommandEncoder> RenderCommandEncoder;
ImGui_ImplMetal_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -185,12 +187,15 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
[commandEncoder setRenderPipelineState:renderPipelineState];
[commandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:vertexBufferOffset atIndex:0];
}
// Draw callbacks
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplMetal_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplMetal_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateLinear atIndex:0]; }
static void ImGui_ImplMetal_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); [bd->RenderCommandEncoder setFragmentSamplerState:bd->SharedMetalContext.samplerStateNearest atIndex:0]; }
// Metal Render function.
void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
@@ -228,6 +233,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
bd->RenderCommandEncoder = commandEncoder;
ImGui_ImplMetal_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
// Will project scissor/clipping rectangles into framebuffer space
@@ -306,6 +312,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
[sharedMetalContext.bufferCache addObject:indexBuffer];
}
}];
bd->RenderCommandEncoder = nil;
}
static void ImGui_ImplMetal_DestroyTexture(ImTextureData* tex)
@@ -382,7 +389,17 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
depthStencilDescriptor.depthWriteEnabled = NO;
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
#ifdef IMGUI_IMPL_METAL_CPP
[samplerDescriptor release];
[depthStencilDescriptor release];
#endif
@@ -399,6 +416,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
ImGui_ImplMetal_DestroyTexture(tex);
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
bd->SharedMetalContext.samplerStateLinear = nil;
bd->SharedMetalContext.samplerStateNearest = nil;
}
bool ImGui_ImplMetal_Init(id<MTLDevice> device)
@@ -415,6 +434,8 @@ bool ImGui_ImplMetal_Init(id<MTLDevice> device)
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal_DrawCallback_ResetRenderState;
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal_DrawCallback_SetSamplerLinear;
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal_DrawCallback_SetSamplerNearest;
bd->SharedMetalContext = [[MetalContext alloc] init];
bd->SharedMetalContext.device = device;
@@ -599,9 +620,9 @@ void ImGui_ImplMetal_Shutdown()
"}\n"
"\n"
"fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
" texture2d<half, access::sample> texture [[texture(0)]]) {\n"
" constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n"
" half4 texColor = texture.sample(linearSampler, in.texCoords);\n"
" texture2d<half, access::sample> texture [[texture(0)]],\n"
" sampler textureSampler [[sampler(0)]]) {\n"
" half4 texColor = texture.sample(textureSampler, in.texCoords);\n"
" return half4(in.color) * texColor;\n"
"}\n";

View File

@@ -255,7 +255,9 @@ struct ImGui_ImplOpenGL3_Data
bool UseBufferSubData;
bool UseTexParameterToSetSampler;
GLuint NextSampler; // Used if !HasBindSampler && UseTexParameterToSetSampler.
GLuint TexSamplers[2]; // Used if IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER && HasBindSimpler (0=linear, 1=nearest).
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
#endif
ImVector<char> TempBuffer;
@@ -404,8 +406,13 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
// Draw callbacks
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[0]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[1]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } }
#else
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
#endif
// OpenGL3 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
@@ -944,7 +951,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
{
ImGui_ImplOpenGL3_InitLoader();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->TexSamplers[0]) { glDeleteSamplers(2, &bd->TexSamplers[0]); bd->TexSamplers[0] = bd->TexSamplers[1] = 0; }
#endif
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }

View File

@@ -328,11 +328,31 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(con
WGPUShaderModuleDescriptor desc = {};
desc.nextInChain = (WGPUChainedStruct*)&wgsl_desc;
// Detect shader compilation errors by using an error scope.
// Flag to be passed into the validation callback `userdata1` pointer.
int validation_error = 0;
wgpuDevicePushErrorScope(bd->wgpuDevice, WGPUErrorFilter_Validation);
WGPUShaderModule module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
WGPUPopErrorScopeCallbackInfo pop_cb = {};
pop_cb.mode = WGPUCallbackMode_AllowSpontaneous;
pop_cb.callback = [](WGPUPopErrorScopeStatus, WGPUErrorType type, WGPUStringView, void* userdata1, void*)
{
if (type == WGPUErrorType_Validation)
*static_cast<int*>(userdata1) = 1;
};
pop_cb.userdata1 = &validation_error;
wgpuDevicePopErrorScope(bd->wgpuDevice, pop_cb);
WGPUProgrammableStageDescriptor stage_desc = {};
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
stage_desc.entryPoint = { "main", WGPU_STRLEN };
#endif
if (module && !validation_error)
{
stage_desc.module = module;
stage_desc.entryPoint = { "main", WGPU_STRLEN };
}
else if (module)
{
wgpuShaderModuleRelease(module);
}
return stage_desc;
}

View File

@@ -36,34 +36,56 @@ HOW TO UPDATE?
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.92.8 WIP (In Progress)
VERSION 1.92.8 (Released 2026-05-12)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.8
Breaking Changes:
- DrawList:
- Obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
- DrawList: swapped the last two arguments of `AddRect()`, `AddPolyline()`, `PathStroke()`.
- Before: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);`
- After: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);`
- Before: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);`
- After: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);`
- Before: `void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);`
- After: `void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);`
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
Effectively the typical call site is changing from:
- Before: `window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);`
- After: `window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);`
Notes:
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
If you are a binding maintainer consider doing something to facilitate transition or error detection.
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
which is part of our new standard draw callbacks. (#9378)
Redirecting the earlier value into the later one when set, so both old and new code should work.
- Backends:
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
- When creating your own descriptor pool (instead of letting backend creates its own):
- Before: need at least IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.
- After: need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
+ IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
- Before: need at least `IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`.
- After: need at least `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
+ `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
- Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)
- After: ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)
- Before: `ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)`
- After: `ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)`
- Kept inline redirection function that ignores the sampler (will obsolete).
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from ImGui_ImplXXXX_RenderState.
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
If there is a legit need/request for them or any render state we can always add them back.
Other Changes:
- DrawList:
- Added room in ImGuiPlatformIO for standard backend-agnostic draw callbacks. Those callbacks
- Added room in `ImGuiPlatformIO` for standard backend-agnostic draw callbacks. Those callbacks
are setup/provided by the backend and available in most of our standard backends.
They allow backend-agnostic code from e.g. switching to a Nearest/Point sampler without
messing with custom Renderer-specific callbacks.
@@ -73,12 +95,13 @@ Other Changes:
Note that some backends might not support all callbacks.
(#9378, #9371, #3590, #8926, #2973, #7485, #7468, #6969, #5118, #7616, #9173, #8322, #7230,
#5999, #6452, #5156, #7342, #7592, #7511)
- Made AddCallback() user data default to Null for convenience.
- Made `AddCallback()` user data default to Null for convenience.
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
- InputText:
- InputTextMultiline: fixed an issue processing deactivation logic when an active
multi-line edit is clipped due to being out of view.
- Fixed a crash when toggling ReadOnly while active. (#9354)
- CharFilter callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
- `CharFilter` callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
- Tables:
- Fixed issues reporting ideal size to parent window/container: (#9352, #7651)
- When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested.
@@ -87,38 +110,70 @@ Other Changes:
- Fixed a single-axis auto-resizing feedback loop issue with nested containers
and varying scrollbar visibility. (#9352)
- Detect and report error when calling End() instead of EndPopup() on a popup. (#9351)
- Child windows with only ImGuiChildFlags_AutoResizeY flag keep using the proportional
default ItemWidth. (#9355)
- Child windows with only `ImGuiChildFlags_AutoResizeY` flag keep using the proportional
default `ItemWidth`. (#9355)
- Using mouse wheel to scroll takes and keeps ownership of the corresponding keys
(e.g. `ImGuiKey_MouseWheelY`) while a wheeling window is locked. (#2604, #3795)
- InputInt, InputFloat, InputScalar:
- Reinstated `ImGuiInputTextFlags_EnterReturnsTrue` support which was removed in 1.91.4.
(#8665, #9299, #8065, #3946, #6284, #9117)
- Fixed the fact that it didn't return true when validating same value.
- Fixed losing value when tabbing out or losing focus.
- Made it that pressing +/- step buttons also return true, which is in line
with 1.91.4 behavior.
- In a majority of cases you should use `IsItemDeactivatedAfterEdit()` instead,
but it still has a few edge cases flaws (to be addressed soon).
- Allow passing a format string that does not display the scalar value.
Parsing input with default format for the type. (#9385) [@FireFox2000000]
- Multi-Select:
- Fixed an issue using Multi-Select within a Table causing column width measurement to
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
which could lead to an extra vertical offset in the Header row. (#8250)
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect1d mode while scrolling.
- Multi-Select + Box-Select:
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect1d` mode while scrolling.
Notably, using mouse wheel while holding a box-selection could lead items close to windows
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
- Box-Select: improved dirty/unclip rectangle logic for ImGuiMultiSelectFlags_BoxSelect2d.
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode, where
- Improved dirty/unclip rectangle logic for `ImGuiMultiSelectFlags_BoxSelect2d`.
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode, where
items out of view wouldn't be properly selected while scrolling while mouse cursor
is hovering outside of selection scope. (#7994, #1861, #6518)
- Box-Select: fixed an issue where items out of horizontal view would sometimes lead
- Fixed an issue where items out of horizontal view would sometimes lead
to incorrect merging of sequential selection requests while also scrolling fast
enough to overlap multiple rows during a frame. (#7994, #1861, #6518)
- Box-Select: fixed an issue using ImGuiMultiSelectFlags_BoxSelect2d mode in a Table
while relying on the TableNextColumn() return value to perform coarse clipping. (#7994)
- Box-Select: disabled merging consecutive selection requests as we have no reliable
way of detecting if user has submitted all consecutives items without clipping gaps,
and ImGuiSelectionUserData is technically opaque storage. (#7994, #1861)
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode in a Table
while relying on the `TableNextColumn()` return value to perform coarse clipping. (#7994)
- Disabled merging consecutive selection requests as we have no reliable
way of detecting if user has submitted all consecutive items without clipping gaps,
and `ImGuiSelectionUserData` is technically opaque storage. (#7994, #1861)
(we will probably bring this back as a minor optimization if we have a way to for
user to tell us ImGuiSelectionUserData are indices)
- Box-Select: fixes for using accross nested child windows. (#8364)
user to tell us `ImGuiSelectionUserData` are indices)
- Fixes for using across nested child windows. (#8364)
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
active. (#7994, #8250, #7821, #7850, #7970)
- Box-Select + Tables: fixed an issue using box-selection in a tables with
items straying out of columns boundaries. (#7994, #2221)
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
before layout has been locked (first row or headers row submitted). (#8250)
- Menus:
- BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when
opening a menu inside a small host window forcing the child menu window to be
repositioned under the mouse cursor. (#8233, #9394)
Done by reworking `BeginMenu()`/`MenuItem()`: they previously avoiding taking
ActiveID + key/click ownership (in order to allow releasing button on another item).
Now they take them and release them once the mouse is moved outside item boundaries.
- Inputs:
- SetItemKeyOwner(): return true if ownership has been requested, which typically
needs to to checked for gating further tests. This is important as the function
may fail. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
- SetItemKeyOwner(): does not set ownership is key is already taken. Effectively
this makes using `SetItemKeyOwner(ImGuiKey_MouseWheelY)` over an item work as
expected while not having item react if a scroll wheel is actively in progress.
May be subject to further redesign, e.g. conditional flags. Feedback welcome!
- Style:
- Checkbox: added `ImGuiCol_CheckboxSelectedBg` to change or accentuate the
background color of checked/mixed checkboxes. (#9392)
- Added `ImGuiStyleVar_DragDropTargetRounding`. (#9056)
- Fixed vertical scrollbar top coordinates when using thick borders on windows
with no title bar and no menu bar. (#9366)
- Fonts:
@@ -131,8 +186,12 @@ Other Changes:
- Tweaked assert triggering when first item height measurement fails, and made it
a better recoverable error. (#9350)
- Misc:
- Minor optimization: reduce redudant label scanning in common widgets.
- Added missing Test Engine hooks for PlotXXX(), VSliderXXX(), TableHeader().
- Minor optimization: reduce redundant label scanning in common widgets.
- Added missing Test Engine hooks for `PlotLines()`, `PlotHistogram()`, `VSliderXXX()`
and `TableHeader()` functions.
- Demo:
- Added simple demo for a scrollable/zoomable image viewer with a grid.
Available in `Examples->Image Viewer` and `Widgets->Images`.
- Backends:
- Added support for new standardized draw callbacks in most backends: (#9378)
- Allegro5: Reset n/a n/a
@@ -140,7 +199,7 @@ Other Changes:
- DX10: Reset SetSamplerLinear SetSamplerNearest
- DX11: Reset SetSamplerLinear SetSamplerNearest
- DX12: Reset SetSamplerLinear SetSamplerNearest
- Metal: Reset *missing* *missing*
- Metal: Reset SetSamplerLinear SetSamplerNearest
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
@@ -148,7 +207,7 @@ Other Changes:
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
(Vulkan backend by @yaz0r, others by @ocornut)
(Vulkan backend by @yaz0r, Metal by @ssh4net, others by @ocornut)
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
functions for legacy GLFW 3.2. (#9003)
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
@@ -158,14 +217,13 @@ Other Changes:
- SDL2: made `ImGui_ImplSDL2_GetContentScaleForWindow()`/`ImGui_ImplSDL2_GetContentScaleForDisplay()`
helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value
and this breaks scaling border size. (#9369)
- WebGPU: always use SPIR-V shader on WGVK, as it cannot be detected at runtime. (#9316, #9246, #9257)
- WebGPU: rework choice/detection of using WGSL/SPIR-V shader on WGVK. (#9316, #9246, #9257, #9387)
- Examples:
- Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141). The later is the
first that supports vcpkg. Onward we will likely stop testing building the library with VS2015.
- GLFW+Vulkan, SDL2+Vulkan, SDL3+Vulkan, Win32+Vulkan: reworked to create a descriptor pool with:
- IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.
- IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
-----------------------------------------------------------------------

17
docs/SECURITY.md Normal file
View File

@@ -0,0 +1,17 @@
# Security Policy
Dear ImGui is primarily designed for developer tools and technical applications running trusted code and trusted data.
Given that the library was not designed as a hardened security boundary against hostile or intentionally malformed inputs:
consider not using it in a context where a crash (through e.g. intentionally malformed inputs) could lead to privilege elevation.
E.g. running in a privileged process and interacting with non-privileged clients feeding code or data to Dear ImGui.
Dear ImGui development efforts are focused on improving developer experience, usability, correctness, and robustness in real-world applications.
We will do our best to reduce e.g. crashes caused by common programmer mistakes.
However, the project does not specifically focus on adversarial fuzzing scenarios, allocation-failure hardening, or highly artificial edge cases that are unlikely to occur in normal usage.
## Reporting a Vulnerability
Considering the above policy, most things may be reported in GitHub Issues.
If you have a reason to disclose privately, please reach out to the contact address listed in README.

View File

@@ -146,6 +146,28 @@ else() # Native/Desktop build
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
@@ -187,6 +209,7 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
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_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)

View File

@@ -141,6 +141,28 @@ else() # Native/Desktop build
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
@@ -183,6 +205,7 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
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_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)

View File

@@ -141,6 +141,28 @@ else() # Native/Desktop build
endif()
if(IMGUI_WGVK_DIR)
find_package(Vulkan REQUIRED)
set(WGVK_PLATFORM_LIBS)
set(WGVK_PLATFORM_DEFS)
if(WIN32)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WIN32_SURFACE=1)
elseif(APPLE)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_METAL_SURFACE=1)
elseif(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(WAYLAND_CLIENT QUIET wayland-client)
if(WAYLAND_CLIENT_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_WAYLAND_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS ${WAYLAND_CLIENT_LIBRARIES})
endif()
find_package(X11 QUIET)
if(X11_FOUND)
list(APPEND WGVK_PLATFORM_DEFS SUPPORT_XLIB_SURFACE=1)
list(APPEND WGVK_PLATFORM_LIBS X11::X11)
endif()
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
endif()
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
endif()
endif()
@@ -182,6 +204,7 @@ if(NOT EMSCRIPTEN) # WegGPU-Native settings
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_compile_definitions(${IMGUI_EXECUTABLE} PRIVATE ${WGVK_PLATFORM_DEFS})
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGVK_DIR}/include)
if (MSVC)
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /std:clatest /experimental:c11atomics)

View File

@@ -3,12 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32616.157
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx11", "example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx9", "example_win32_directx9\example_win32_directx9.vcxproj", "{4165A294-21F2-44CA-9B38-E3F935ABADF5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx10", "example_win32_directx10\example_win32_directx10.vcxproj", "{345A953E-A004-4648-B442-DC5F9F11068C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx11", "example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx12", "example_win32_directx12\example_win32_directx12.vcxproj", "{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_opengl2", "example_glfw_opengl2\example_glfw_opengl2.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}"

View File

@@ -1,7 +0,0 @@
project "imgui"
kind "StaticLib"
files { "../*.h", "../*.cpp" }
vpaths { ["imgui"] = { "../*.cpp", "../*.h", "../misc/debuggers/*.natvis" } }
filter { "toolset:msc*" }
files { "../misc/debuggers/*.natvis" }

View File

@@ -1,322 +0,0 @@
-- We use Premake5 to generate project files (Visual Studio solutions, XCode solutions, Makefiles, etc.)
-- Download Premake5: at https://premake.github.io/download
-- YOU NEED PREMAKE 5.0.0-alpha10 or later
--------- HELP
-- To reduce friction for people who don't aren't used to Premake, we list some concrete usage examples.
if _ACTION == nil then
print "-----------------------------------------"
print " DEAR IMGUI EXAMPLES - PROJECT GENERATOR"
print "-----------------------------------------"
print "Usage:"
print " premake5 [generator] [options]"
print "Examples:"
print " premake5 vs2010"
print " premake5 vs2019 --with-sdl2 --with-vulkan"
print " premake5 xcode4 --with-glfw"
print " premake5 gmake2 --with-glfw --cc=clang"
print "Generators:"
print " codelite gmake gmake2 vs2008 vs2010 vs2012 vs2013 vs2015 vs2017 xcode4 etc."
print "Options:"
print " --with-dx9 Enable dear imgui DirectX 9 example"
print " --with-dx10 Enable dear imgui DirectX 10 example"
print " --with-dx11 Enable dear imgui DirectX 11 example"
print " --with-dx12 Enable dear imgui DirectX 12 example (vs2015+)"
print " --with-glfw Enable dear imgui GLFW examples"
print " --with-sdl2 Enable dear imgui SDL2 examples"
print " --with-vulkan Enable dear imgui Vulkan example"
print " --cc=clang Compile with Clang"
print " --cc=gcc Compile with GCC"
print "Project and object files will be created in the build/ folder. You can delete your build/ folder at any time."
print ""
end
---------- OPTIONS
newoption { trigger = "with-dx9", description="Enable dear imgui DirectX 9 example" }
newoption { trigger = "with-dx10", description="Enable dear imgui DirectX 10 example" }
newoption { trigger = "with-dx11", description="Enable dear imgui DirectX 11 example" }
newoption { trigger = "with-dx12", description="Enable dear imgui DirectX 12 example" }
newoption { trigger = "with-glfw", description="Enable dear imgui GLFW examples" }
newoption { trigger = "with-sdl2", description="Enable dear imgui SDL2 examples" }
newoption { trigger = "with-vulkan", description="Enable dear imgui Vulkan example" }
-- Enable/detect default options under Windows
if _ACTION ~= nil and ((os.istarget ~= nil and os.istarget("windows")) or (os.is ~= nil and os.is("windows"))) then
print("( enabling --with-dx9 )");
print("( enabling --with-dx10 )");
print("( enabling --with-dx11 )");
_OPTIONS["with-dx9"] = 1
_OPTIONS["with-dx10"] = 1
_OPTIONS["with-dx11"] = 1
if _ACTION >= "vs2015" then
print("( enabling --with-dx12 because compiler is " .. _ACTION .. " )");
_OPTIONS["with-dx12"] = 1
end
print("( enabling --with-glfw because GLFW is included in the libs/ folder )");
_OPTIONS["with-glfw"] = 1
if os.getenv("SDL2_DIR") then
print("( enabling --with-sdl2 because SDL2_DIR environment variable was found )");
_OPTIONS["with-sdl2"] = 1
end
if os.getenv("VULKAN_SDK") then
print("( enabling --with-vulkan because VULKAN_SDK environment variable was found )");
_OPTIONS["with-vulkan"] = 1
end
end
--------- HELPER FUNCTIONS
-- Helper function: add dear imgui source files into project
function imgui_as_src(fs_path, project_path)
if (project_path == nil) then project_path = fs_path; end; -- default to same virtual folder as the file system folder (in this project it would be ".." !)
files { fs_path .. "/*.cpp", fs_path .. "/*.h" }
includedirs { fs_path, fs_path .. "/backends" }
vpaths { [project_path] = { fs_path .. "/*.*", fs_path .. "/misc/debuggers/*.natvis" } } -- add in a specific folder of the Visual Studio project
filter { "toolset:msc*" }
files { fs_path .. "/misc/debuggers/*.natvis" }
filter {}
end
-- Helper function: add dear imgui as a library (uncomment the 'include "premake5-lib"' line)
--include "premake5-lib"
function imgui_as_lib(fs_path)
includedirs { fs_path, fs_path .. "/backends" }
links "imgui"
end
--------- SOLUTION, PROJECTS
workspace "imgui_examples"
configurations { "Debug", "Release" }
platforms { "x86", "x86_64" }
location "build/"
symbols "On"
warnings "Extra"
--flags { "FatalCompileWarnings"}
filter { "configurations:Debug" }
optimize "Off"
filter { "configurations:Release" }
optimize "On"
filter { "toolset:clang", "system:windows" }
buildoptions { "-Xclang", "-flto-visibility-public-std" } -- Remove "warning LNK4049: locally defined symbol ___std_terminate imported"
-- example_win32_directx11 (Win32 + DirectX 11)
-- We have DX11 as the first project because this is what Visual Studio uses
if (_OPTIONS["with-dx11"]) then
project "example_win32_directx11"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
files { "../backends/imgui_impl_win32.*", "../backends/imgui_impl_dx11.*", "example_win32_directx11/*.cpp", "example_win32_directx11/*.h", "README.txt" }
vpaths { ["sources"] = "./**" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100" }
includedirs { "$(DXSDK_DIR)/Include" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100", "platforms:x86" }
libdirs { "$(DXSDK_DIR)/Lib/x86" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100", "platforms:x86_64" }
libdirs { "$(DXSDK_DIR)/Lib/x64" }
filter { "system:windows" }
links { "d3d11", "d3dcompiler", "dxgi" }
end
-- example_win32_directx9 (Win32 + DirectX 9)
if (_OPTIONS["with-dx9"]) then
project "example_win32_directx9"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
files { "../backends/imgui_impl_win32.*", "../backends/imgui_impl_dx9.*", "example_win32_directx9/*.cpp", "example_win32_directx9/*.h", "README.txt" }
vpaths { ["sources"] = "./**" }
filter { "system:windows" }
links { "d3d9" }
end
-- example_win32_directx10 (Win32 + DirectX 10)
if (_OPTIONS["with-dx10"]) then
project "example_win32_directx10"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
files { "../backends/imgui_impl_win32.*", "../backends/imgui_impl_dx10.*", "example_win32_directx10/*.cpp", "example_win32_directx10/*.h", "README.txt" }
vpaths { ["sources"] = "./**" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100" }
includedirs { "$(DXSDK_DIR)/Include" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100", "platforms:x86" }
libdirs { "$(DXSDK_DIR)/Lib/x86" }
filter { "system:windows", "toolset:msc-v80 or msc-v90 or msc-v100", "platforms:x86_64" }
libdirs { "$(DXSDK_DIR)/Lib/x64" }
filter { "system:windows" }
links { "d3d10", "d3dcompiler", "dxgi" }
end
-- example_win32_directx12 (Win32 + DirectX 12)
if (_OPTIONS["with-dx12"]) then
project "example_win32_directx12"
kind "ConsoleApp"
systemversion "10.0.16299.0"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
files { "../backends/imgui_impl_win32.*", "../backends/imgui_impl_dx12.*", "example_win32_directx12/*.cpp", "example_win32_directx12/*.h", "README.txt" }
vpaths { ["sources"] = "./**" }
filter { "system:windows" }
links { "d3d12", "d3dcompiler", "dxgi" }
end
-- example_glfw_opengl2 (GLFW + OpenGL2)
if (_OPTIONS["with-glfw"]) then
project "example_glfw_opengl2"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
files { "../backends/imgui_impl_glfw.*", "../backends/imgui_impl_opengl2.*", "example_glfw_opengl2/*.h", "example_glfw_opengl2/*.cpp", "README.txt"}
vpaths { ["sources"] = "./**" }
includedirs { "libs/glfw/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "libs/glfw/lib-vc2010-32" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "libs/glfw/lib-vc2010-64" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "opengl32", "glfw3" }
filter { "system:linux" }
links { "glfw3" }
filter { "system:macosx" }
libdirs { "/usr/local/lib" }
links { "glfw" }
linkoptions { "-framework OpenGL" }
end
-- example_glfw_opengl3 (GLFW + OpenGL3)
if (_OPTIONS["with-glfw"]) then
project "example_glfw_opengl3"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_glfw.*", "../backends/imgui_impl_opengl3.*", "example_glfw_opengl3/*.h", "example_glfw_opengl3/*.cpp", "./README.txt" }
includedirs { "libs/glfw/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "libs/glfw/lib-vc2010-32" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "libs/glfw/lib-vc2010-64" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "opengl32", "glfw3" }
filter { "system:linux" }
links { "glfw3" }
filter { "system:macosx" }
libdirs { "/usr/local/lib" }
links { "glfw" }
linkoptions { "-framework OpenGL" }
end
-- example_glfw_vulkan (GLFW + Vulkan)
if (_OPTIONS["with-vulkan"]) then
project "example_glfw_vulkan"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_glfw*", "../backends/imgui_impl_vulkan.*", "example_glfw_vulkan/*.h", "example_glfw_vulkan/*.cpp", "./README.txt" }
includedirs { "libs/glfw/include", "%VULKAN_SDK%/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "libs/glfw/lib-vc2010-32", "%VULKAN_SDK%/lib32" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "libs/glfw/lib-vc2010-64", "%VULKAN_SDK%/lib" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "vulkan-1", "glfw3" }
filter { "system:linux" }
links { "glfw3" } -- FIXME: missing Vulkan. missing macosx version
end
-- example_null (no rendering)
if (true) then
project "example_null"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "example_null/*.h", "example_null/*.cpp", "./README.txt" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
end
-- example_sdl2_sdlrenderer2 (SDL2 + SDL_Renderer)
if (_OPTIONS["with-sdl2"]) then
project "example_sdl2_sdlrenderer2"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_sdl2*", "../backends/imgui_impl_sdlrenderer2.*", "example_sdl2_sdlrenderer2/*.h", "example_sdl2_sdlrenderer2/*.cpp", "./README.txt" }
includedirs { "%SDL2_DIR%/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "%SDL2_DIR%/lib/x86" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "%SDL2_DIR%/lib/x64" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "SDL2", "SDL2main" }
end
-- example_sdl2_opengl2 (SDL2 + OpenGL2)
if (_OPTIONS["with-sdl2"]) then
project "example_sdl2_opengl2"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_sdl2*", "../backends/imgui_impl_opengl2.*", "example_sdl2_opengl2/*.h", "example_sdl2_opengl2/*.cpp", "./README.txt" }
includedirs { "%SDL2_DIR%/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "%SDL2_DIR%/lib/x86" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "%SDL2_DIR%/lib/x64" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "SDL2", "SDL2main", "opengl32" }
end
-- example_sdl2_opengl3 (SDL2 + OpenGL3)
if (_OPTIONS["with-sdl2"]) then
project "example_sdl2_opengl3"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_sdl2*", "../backends/imgui_impl_opengl3.*", "example_sdl2_opengl3/*.h", "example_sdl2_opengl3/*.cpp", "./README.txt" }
includedirs { "%SDL2_DIR%/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "%SDL2_DIR%/lib/x86" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "%SDL2_DIR%/lib/x64" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "SDL2", "SDL2main", "opengl32" }
end
-- example_sdl2_vulkan (SDL2 + Vulkan)
if (_OPTIONS["with-sdl2"] and _OPTIONS["with-vulkan"]) then
project "example_sdl2_vulkan"
kind "ConsoleApp"
imgui_as_src ("..", "imgui")
--imgui_as_lib ("..")
vpaths { ["sources"] = "./**" }
files { "../backends/imgui_impl_sdl2*", "../backends/imgui_impl_vulkan.*", "example_sdl2_vulkan/*.h", "example_sdl2_vulkan/*.cpp", "./README.txt" }
includedirs { "%SDL2_DIR%/include", "%VULKAN_SDK%/include" }
filter { "system:windows", "platforms:x86" }
libdirs { "%SDL2_DIR%/lib/x86", "%VULKAN_SDK%/lib32" }
filter { "system:windows", "platforms:x86_64" }
libdirs { "%SDL2_DIR%/lib/x64", "%VULKAN_SDK%/lib" }
filter { "system:windows" }
ignoredefaultlibraries { "msvcrt" }
links { "SDL2", "SDL2main", "vulkan-1" }
end

155
imgui.cpp
View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (main code and documentation)
// Help:
@@ -395,7 +395,28 @@ 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/04/23 (1.92.8) - Obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
- Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);
- After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);
- Before: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
- After: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
- Before: void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);
- After: void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
Effectively the typical call site is changing from:
- Before: window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);
- After: window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);
Notes:
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
If you are a binding maintainer consider doing something to facilitate transition or error detection.
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
- 2026/04/23 (1.92.8) - DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
- 2026/04/22 (1.92.8) - Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler.
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
- When creating your own descriptor pool (instead of letting backend creates its own): need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
@@ -3659,6 +3680,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorSize)}, // ImGuiStyleVar_SeparatorSize
@@ -3759,6 +3781,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
case ImGuiCol_CheckMark: return "CheckMark";
case ImGuiCol_CheckboxSelectedBg: return "CheckboxSelectedBg";
case ImGuiCol_SliderGrab: return "SliderGrab";
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
case ImGuiCol_Button: return "Button";
@@ -3926,8 +3949,8 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
text_end_full = FindRenderedTextEnd(text);
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 6), IM_COL32(0, 0, 255, 255));
//draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y - 2), ImVec2(ellipsis_max_x, pos_max.y + 3), IM_COL32(0, 255, 0, 255));
//draw_list->AddLineV(pos_max.x, pos_min.y - 4, pos_max.y + 6, IM_COL32(0, 0, 255, 255));
//draw_list->AddLineV(ellipsis_max_x, pos_min.y - 2, pos_max.y + 3, IM_COL32(0, 255, 0, 255));
// FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
if (text_size.x > pos_max.x - pos_min.x)
@@ -3972,8 +3995,8 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders
const float border_size = g.Style.FrameBorderSize;
if (borders && border_size > 0.0f)
{
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
}
}
@@ -3984,8 +4007,8 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
const float border_size = g.Style.FrameBorderSize;
if (border_size > 0.0f)
{
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
}
}
@@ -4020,7 +4043,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
const float thickness = 2.0f;
if (flags & ImGuiNavRenderCursorFlags_Compact)
{
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
}
else
{
@@ -4029,7 +4052,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
bool fully_visible = window->ClipRect.Contains(display_rect);
if (!fully_visible)
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
if (!fully_visible)
window->DrawList->PopClipRect();
}
@@ -4063,7 +4086,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI);
float a_max = a_min + IM_PI * 1.65f;
draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max);
draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
draw_list->PathStroke(col_fill, 3.0f * scale);
}
draw_list->PopTexture();
}
@@ -4697,7 +4720,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
g.ActiveIdIsJustActivated = (g.ActiveId != id);
if (g.ActiveIdIsJustActivated)
{
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "", id, window ? window->Name : "");
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() 0x%08X in \"%s\"%*s(previously 0x%08X in \"%s\")\n", id, window ? window->Name : "",
ImMax(0, 20 - (int)(window ? strlen(window->Name) : 0)), "", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "");
g.ActiveIdTimer = 0.0f;
g.ActiveIdHasBeenPressedBefore = false;
g.ActiveIdHasBeenEditedBefore = false;
@@ -4753,8 +4777,12 @@ void ImGui::MarkItemEdited(ImGuiID id)
// This marking is to be able to provide info for IsItemDeactivatedAfterEdit().
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
ImGuiContext& g = *GImGui;
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_EditedInternal;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
return;
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
if (g.ActiveId == id || g.ActiveId == 0)
{
// FIXME: Can't we fully rely on LastItemData yet?
@@ -4768,9 +4796,6 @@ void ImGui::MarkItemEdited(ImGuiID id)
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
}
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
@@ -4935,7 +4960,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
{
g.HoveredIdPreviousFrameItemCount++;
if (g.DebugDrawIdConflictsId == id)
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, 2.0f);
}
#endif
@@ -5732,7 +5757,7 @@ void ImGui::NewFrame()
g.CurrentWindowStack.resize(0);
g.BeginPopupStack.resize(0);
g.ItemFlagsStack.resize(0);
g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups); // Default flags
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_); // Default flags
g.CurrentItemFlags = g.ItemFlagsStack.back();
g.GroupStack.resize(0);
@@ -5967,7 +5992,7 @@ static void ImGui::RenderDimmedBackgrounds()
if (window->DrawList->CmdBuffer.Size == 0)
window->DrawList->AddDrawCmd();
window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f); // FIXME-DPI
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 3.0f); // FIXME-DPI
window->DrawList->PopClipRect();
}
}
@@ -7127,7 +7152,7 @@ static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU
const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
window->DrawList->PathStroke(border_col, border_size);
}
static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
@@ -7136,7 +7161,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
const float border_size = window->WindowBorderSize;
const ImU32 border_col = GetColorU32(ImGuiCol_Border);
if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, window->WindowBorderSize);
else if (border_size > 0.0f)
{
if (window->ChildFlags & ImGuiChildFlags_ResizeX) // Similar code as 'resize_border_mask' computation in UpdateWindowManualResize() but we specifically only always draw explicit child resize border.
@@ -7153,7 +7178,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
{
float y = window->Pos.y + window->TitleBarHeight - 1;
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size * 0.5f, y), ImVec2(window->Pos.x + window->Size.x - border_size * 0.5f, y), border_col, g.Style.FrameBorderSize);
window->DrawList->AddLineH(window->Pos.x + border_size * 0.5f, window->Pos.x + window->Size.x - border_size * 0.5f, y, border_col, g.Style.FrameBorderSize);
}
}
@@ -7201,7 +7226,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (bg_col & IM_COL32_A_MASK)
{
ImRect bg_rect(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size);
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom;
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersBottom;
ImDrawList* bg_draw_list = window->DrawList;
bg_draw_list->AddRectFilled(bg_rect.Min, bg_rect.Max, bg_col, window_rounding, bg_rounding_flags);
}
@@ -7221,7 +7246,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
window->DrawList->AddLine(menu_bar_rect.GetBL() + ImVec2(window_border_size * 0.5f, 0.0f), menu_bar_rect.GetBR() - ImVec2(window_border_size * 0.5f, 0.0f), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size * 0.5f, menu_bar_rect.Max.x - window_border_size * 0.5f, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
}
// Scrollbars
@@ -9011,7 +9036,7 @@ ImFont* ImGui::GetDefaultFont()
return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
}
// EXPERIMENTAL: DO NOT USE YET.
// EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates.
void ImGui::RegisterUserTexture(ImTextureData* tex)
{
ImGuiContext& g = *GImGui;
@@ -10341,15 +10366,21 @@ void ImGui::UpdateMouseWheel()
LockWheelingWindow(NULL, 0.0f);
}
ImVec2 wheel;
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheelH : 0.0f;
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheel : 0.0f;
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
ImGuiWindow* mouse_window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
if (!mouse_window || mouse_window->Collapsed)
return;
ImGuiID owner_id = mouse_window->ID;
ImVec2 wheel;
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, owner_id) ? g.IO.MouseWheelH : 0.0f;
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, owner_id) ? g.IO.MouseWheel : 0.0f;
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
if (g.WheelingWindow != NULL)
{
SetKeyOwner(ImGuiKey_MouseWheelX, owner_id);
SetKeyOwner(ImGuiKey_MouseWheelY, owner_id);
}
// Zoom / Scale window
// FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
@@ -10653,6 +10684,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
// - SetKeyOwner(..., None) : clears owner
// - SetKeyOwner(..., Any, !Lock) : illegal (assert)
// - SetKeyOwner(..., Any or None, Lock) : set lock
// Ownership is automatically released on the frame after a release, see code in UpdateKeyboardInputs().
void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
{
ImGuiContext& g = *GImGui;
@@ -10679,30 +10711,34 @@ void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, I
if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
}
// This is more or less equivalent to:
// This is more or less equivalent to a fancier version of:
// if (IsItemHovered() || IsItemActive())
// SetKeyOwner(key, GetItemID());
// Extensive uses of that (e.g. many calls for a single item) may want to manually perform the tests once and then call SetKeyOwner() multiple times.
// More advanced usage scenarios may want to call SetKeyOwner() manually based on different condition.
// Worth noting is that only one item can be hovered and only one item can be active, therefore this usage pattern doesn't need to bother with routing and priority.
void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
bool ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiID id = g.LastItemData.ID;
if (id == 0 || (g.HoveredId != id && g.ActiveId != id))
return;
return false;
if ((flags & ImGuiInputFlags_CondMask_) == 0)
flags |= ImGuiInputFlags_CondDefault_;
if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive)))
{
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function!
if (!TestKeyOwner(key, id))
return false;
SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_);
return true;
}
return false;
}
void ImGui::SetItemKeyOwner(ImGuiKey key)
bool ImGui::SetItemKeyOwner(ImGuiKey key)
{
SetItemKeyOwner(key, ImGuiInputFlags_None);
return SetItemKeyOwner(key, ImGuiInputFlags_None);
}
// This is the only public API until we expose owner_id versions of the API as replacements.
@@ -12453,6 +12489,17 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext
return false;
}
// As we bypass BeginChild(), set ImGuiChildFlags_AlwaysAutoResize as it is checked independently from ImGuiWindowFlags_AlwaysAutoResize for now (see #9355)
// Ideally we should remove setting ImGuiWindowFlags_AlwaysAutoResize in BeginChild().
if ((extra_window_flags & ImGuiWindowFlags_ChildWindow) && (extra_window_flags & ImGuiWindowFlags_AlwaysAutoResize))
{
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
g.NextWindowData.ChildFlags |= ImGuiChildFlags_AlwaysAutoResize;
else
g.NextWindowData.ChildFlags = ImGuiChildFlags_AlwaysAutoResize;
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
}
char name[128];
IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
ImFormatString(name, IM_COUNTOF(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth
@@ -15117,7 +15164,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
{
ImRect bb = g.DragDropTargetRect;
bb.Expand(-3.5f);
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb);
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb, g.Style.DragDropTargetRounding);
}
else if (draw_target_rect)
{
@@ -15148,16 +15195,16 @@ void ImGui::RenderDragDropTargetRectForItem(const ImRect& bb)
bool push_clip_rect = !window->ClipRect.Contains(bb_display);
if (push_clip_rect)
window->DrawList->PushClipRectFullScreen();
RenderDragDropTargetRectEx(window->DrawList, bb_display);
RenderDragDropTargetRectEx(window->DrawList, bb_display, g.Style.DragDropTargetRounding);
if (push_clip_rect)
window->DrawList->PopClipRect();
}
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb)
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding)
{
ImGuiContext& g = *GImGui;
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), g.Style.DragDropTargetRounding, 0);
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), g.Style.DragDropTargetRounding, 0, g.Style.DragDropTargetBorderSize);
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), rounding, 0);
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), rounding, g.Style.DragDropTargetBorderSize);
}
const ImGuiPayload* ImGui::GetDragDropPayload()
@@ -16259,7 +16306,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0f);
draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
@@ -16682,7 +16729,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
if (IsItemHovered())
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
Indent();
char buf[128];
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
@@ -16697,7 +16744,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
}
}
else
@@ -16706,7 +16753,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
Selectable(buf);
if (IsItemHovered())
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
}
}
Unindent();
@@ -17114,7 +17161,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
draw_list->AddRect(r.Min, r.Max, col, 0.0f, thickness);
}
}
else
@@ -17291,7 +17338,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
{
ImDrawListFlags backup_flags = fg_draw_list->Flags;
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed);
fg_draw_list->Flags = backup_flags;
}
}
@@ -17319,7 +17366,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
for (int n = 0; n < 3; n++, idx_n++)
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
if (show_mesh)
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed); // In yellow: mesh triangles
}
// Draw bounding boxes
if (show_aabb)
@@ -17600,8 +17647,8 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
{
ImDrawList* draw_list = GetForegroundDrawList(tab_bar->Window);
draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
draw_list->AddLineV(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
draw_list->AddLineV(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
}
if (open)
{
@@ -17930,8 +17977,8 @@ void ImGui::DebugDrawCursorPos(ImU32 col)
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 pos = window->DC.CursorPos;
window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
window->DrawList->AddLineV(pos.x, pos.y - 3.0f, pos.y + 4.0f, col, 1.0f);
window->DrawList->AddLineH(pos.x - 3.0f, pos.x + 4.0f, pos.y, col, 1.0f);
}
// Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList
@@ -17942,9 +17989,9 @@ void ImGui::DebugDrawLineExtents(ImU32 col)
float curr_x = window->DC.CursorPos.x;
float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y1, col, 1.0f);
window->DrawList->AddLineV(curr_x - 0.5f, line_y1, line_y2, col, 1.0f);
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y2, col, 1.0f);
}
// Draw last item rect in ForegroundDrawList (so it is always visible)
@@ -18314,7 +18361,7 @@ void ImGui::ShowFontSelector(const char* label)
"- Load additional fonts with io.Fonts->AddFontXXX() functions.\n"
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
"- Read FAQ and docs/FONTS.md for more details.\n"
"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
"- Legacy backend: if you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
}
#endif // #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS)

47
imgui.h
View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (headers)
// Help:
@@ -29,8 +29,8 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.8 WIP"
#define IMGUI_VERSION_NUM 19274
#define IMGUI_VERSION "1.92.8"
#define IMGUI_VERSION_NUM 19280
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -1092,10 +1092,11 @@ namespace ImGui
// Inputs Utilities: Key/Input Ownership [BETA]
// - One common use case would be to allow your items to disable standard inputs behaviors such
// as Tab or Alt key handling, Mouse Wheel scrolling, etc.
// e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling.
// e.g. `Button(...); if (SetItemKeyOwner(ImGuiKey_MouseWheelY)) { ... }` to make hovering/activating a button disable wheel for scrolling.
// - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them.
// - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function.
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
// Inputs Utilities: Mouse
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
@@ -1755,6 +1756,7 @@ enum ImGuiCol_
ImGuiCol_ScrollbarGrabHovered,
ImGuiCol_ScrollbarGrabActive,
ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle
ImGuiCol_CheckboxSelectedBg, // Checkbox background when Selected, otherwise use FrameBg
ImGuiCol_SliderGrab,
ImGuiCol_SliderGrabActive,
ImGuiCol_Button,
@@ -1852,6 +1854,7 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
@@ -2328,7 +2331,7 @@ struct ImGuiStyle
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
float DragDropTargetRounding; // Radius of the drag and drop target frame.
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
float ColorMarkerSize; // Size of R/G/B/A color markers for ColorEdit4() and for Drags/Sliders when using ImGuiSliderFlags_ColorMarkers.
@@ -3239,16 +3242,15 @@ struct ImDrawListSplitter
};
// Flags for ImDrawList functions
// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
enum ImDrawFlags_
{
ImDrawFlags_None = 0,
ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
@@ -3256,6 +3258,7 @@ enum ImDrawFlags_
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
ImDrawFlags_InvalidMask_ = (ImDrawFlags)0x8000000F,
};
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
@@ -3321,7 +3324,9 @@ struct ImDrawList
// In future versions we will use textures to provide cheaper and higher-quality circles.
// Use AddNgon() and AddNgonFilled() functions if you need to guarantee a specific number of sides.
IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
@@ -3342,7 +3347,7 @@ struct ImDrawList
// General polygon
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library.
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
@@ -3362,7 +3367,7 @@ struct ImDrawList
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
inline void PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0) { AddPolyline(_Path.Data, _Path.Size, col, thickness, flags); _Path.Size = 0; }
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
@@ -3410,8 +3415,15 @@ struct ImDrawList
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { AddRect(p_min, p_max, col, rounding, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) { AddPolyline(points, num_points, col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void PathStroke(ImU32 col, ImDrawFlags flags, float thickness) { PathStroke(col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
#else
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
#endif
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
@@ -3523,6 +3535,7 @@ struct ImTextureData
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
// Functions
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
~ImTextureData() { DestroyPixels(); }
IMGUI_API void Create(ImTextureFormat format, int w, int h);
@@ -3678,13 +3691,13 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
IMGUI_API void RemoveFont(ImFont* font);
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures).
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
// As we are transitioning toward a new font system, we expect to obsolete those soon:
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -4017,11 +4030,11 @@ struct ImGuiPlatformIO
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
void* Renderer_RenderState;
// Standard draw callbacks
// Standard draw callbacks provided by renderer backend.
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
ImDrawCallback DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
ImDrawCallback DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request to set current texture sampling using Backend Specific data.
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
//------------------------------------------------------------------
// Output

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (demo code)
// Help:
@@ -73,6 +73,7 @@ Index of this file:
// [SECTION] Demo Window / ShowDemoWindow()
// [SECTION] DemoWindowMenuBar()
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
// [SECTION] Helpers: ExampleImageViewer
// [SECTION] DemoWindowWidgetsBasic()
// [SECTION] DemoWindowWidgetsBullets()
// [SECTION] DemoWindowWidgetsCollapsingHeaders()
@@ -108,6 +109,7 @@ Index of this file:
// [SECTION] User Guide / ShowUserGuide()
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
@@ -238,6 +240,7 @@ static void ShowExampleAppAssetsBrowser(bool* p_open);
static void ShowExampleAppConsole(bool* p_open);
static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleAppDocuments(bool* p_open);
static void ShowExampleAppImageViewer(bool* p_open);
static void ShowExampleAppLog(bool* p_open);
static void ShowExampleAppLayout(bool* p_open);
static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data);
@@ -308,6 +311,7 @@ struct ImGuiDemoWindowData
bool ShowAppConsole = false;
bool ShowAppCustomRendering = false;
bool ShowAppDocuments = false;
bool ShowAppImageViewer = false;
bool ShowAppLog = false;
bool ShowAppLayout = false;
bool ShowAppPropertyEditor = false;
@@ -353,6 +357,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (demo_data.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); }
if (demo_data.ShowAppConsole) { ShowExampleAppConsole(&demo_data.ShowAppConsole); }
if (demo_data.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); }
if (demo_data.ShowAppImageViewer) { ShowExampleAppImageViewer(&demo_data.ShowAppImageViewer); }
if (demo_data.ShowAppLog) { ShowExampleAppLog(&demo_data.ShowAppLog); }
if (demo_data.ShowAppLayout) { ShowExampleAppLayout(&demo_data.ShowAppLayout); }
if (demo_data.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); }
@@ -677,6 +682,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole);
ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering);
ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments);
ImGui::MenuItem("Image Viewer", NULL, &demo_data->ShowAppImageViewer);
ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog);
ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor);
ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout);
@@ -708,7 +714,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
ImGui::Checkbox("Highlight ID Conflicts", &io.ConfigDebugHighlightIdConflicts);
ImGui::EndDisabled();
ImGui::Checkbox("Assert on error recovery", &io.ConfigErrorRecoveryEnableAssert);
ImGui::TextDisabled("(see Demo->Configuration for details & more)");
ImGui::TextDisabled("(see Demo->Configuration for more)");
ImGui::EndMenu();
}
ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
@@ -825,6 +831,87 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree()
return node_L0;
}
//-----------------------------------------------------------------------------
// [SECTION] Helpers: ExampleImageViewer
//-----------------------------------------------------------------------------
struct ExampleImageViewerData
{
ImU32 ImageBgColor = IM_COL32(100, 100, 100, 255);
ImU32 GridColor = IM_COL32(255, 255, 255, 100);
bool GridEnabled = true;
bool ViewReset = true;
ImVec2 ViewOffset; // in image space
float Zoom = 10.0f;
float ZoomMin = 1.0f;
float ZoomMax = 10000.0f;
};
static void ExampleImageViewer_DrawOptions(ExampleImageViewerData* data)
{
ImGui::SetNextItemShortcut(ImGuiKey_G, ImGuiInputFlags_Tooltip); // | ImGuiInputFlags_RouteGlobal
ImGui::Checkbox("Grid", &data->GridEnabled);
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10.0f);
float zoom_100 = data->Zoom * 100.0f;
if (ImGui::DragFloat("##Zoom", &zoom_100, 5.0f, data->ZoomMin * 100.0f, data->ZoomMax * 100.0f, "%.0f%%", ImGuiSliderFlags_AlwaysClamp))
data->Zoom = zoom_100 / 100.0f;
}
static void ExampleImageViewer_DrawCanvas(ExampleImageViewerData* data, ImVec2 canvas_size, ImTextureRef image_tex_ref, int image_w, int image_h)
{
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
IM_ASSERT(canvas_size.x >= 0.0f && canvas_size.y >= 0.0f);
// Layout canvas
ImGui::InvisibleButton("##Canvas", canvas_size);
ImVec2 canvas_min = ImGui::GetItemRectMin();
ImVec2 canvas_max = ImGui::GetItemRectMax();
if (data->ViewReset)
data->ViewOffset = ImVec2((canvas_size.x * 0.5f / data->Zoom) - 0.5f, (canvas_size.y * 0.5f / data->Zoom) - 0.5f); // Add half a pixel padding
data->ViewReset = false;
// Handle inputs
if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY))
if (io.MouseWheel != 0.0f)
data->Zoom = IM_CLAMP(data->Zoom * (1.0f + io.MouseWheel * 0.10f), data->ZoomMin, data->ZoomMax);
float zoom = data->Zoom; // (float)(int)ViewZoom;
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0))
{
data->ViewOffset.x -= io.MouseDelta.x / zoom;
data->ViewOffset.y -= io.MouseDelta.y / zoom;
}
// Display image
ImVec2 image_min, image_max;
image_min.x = (float)(int)((canvas_min.x - (data->ViewOffset.x * zoom)) + (canvas_size.x * 0.5f));
image_min.y = (float)(int)((canvas_min.y - (data->ViewOffset.y * zoom)) + (canvas_size.y * 0.5f));
image_max.x = (float)(int)(image_min.x + image_w * zoom);
image_max.y = (float)(int)(image_min.y + image_h * zoom);
draw_list->AddRect(ImVec2(canvas_min.x - 1.0f, canvas_min.y - 1.0f), ImVec2(canvas_max.x + 1.0f, canvas_max.y + 1.0f), IM_COL32(255, 255, 255, 255));
draw_list->PushClipRect(canvas_min, canvas_max, true);
draw_list->AddRectFilled(image_min, image_max, data->ImageBgColor);
if (platform_io.DrawCallback_SetSamplerNearest != NULL)
draw_list->AddCallback(platform_io.DrawCallback_SetSamplerNearest);
draw_list->AddImage(image_tex_ref, image_min, image_max);
if (platform_io.DrawCallback_SetSamplerLinear != NULL)
draw_list->AddCallback(ImGui::GetPlatformIO().DrawCallback_SetSamplerLinear);
// Display grid lines for visible pixels
if (data->GridEnabled && zoom > 6.0f)
{
const float step = (float)zoom;
for (int px = (int)((canvas_min.x - image_min.x) / step); px <= (int)((canvas_max.x - image_min.x) / step); px++)
draw_list->AddLineV(image_min.x + px * step, canvas_min.y, canvas_max.y, data->GridColor, 1.0f);
for (int py = (int)((canvas_min.y - image_min.y) / step); py <= (int)((canvas_max.y - image_min.y) / step); py++)
draw_list->AddLineH(canvas_min.x, canvas_max.x, image_min.y + py * step, data->GridColor, 1.0f);
}
draw_list->PopClipRect();
}
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsBasic()
//-----------------------------------------------------------------------------
@@ -1802,40 +1889,29 @@ static void DemoWindowWidgetsImages()
// - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// Grab the current texture identifier used by the font atlas.
ImTextureRef my_tex_id = io.Fonts->TexRef;
ImFontAtlas* atlas = io.Fonts;
ImTextureRef my_tex_id = atlas->TexRef;
float my_tex_w = (float)atlas->TexData->Width; // Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
float my_tex_h = (float)atlas->TexData->Height;
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
// Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
float my_tex_w = (float)io.Fonts->TexData->Width;
float my_tex_h = (float)io.Fonts->TexData->Height;
// Basic drawing
ImGui::SeparatorText("Image()/ImageWithBg() function");
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::PopStyleVar();
{
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
if (ImGui::BeginItemTooltip())
{
float region_sz = 32.0f;
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
float zoom = 4.0f;
if (region_x < 0.0f) { region_x = 0.0f; }
else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
if (region_y < 0.0f) { region_y = 0.0f; }
else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::EndTooltip();
}
ImGui::PopStyleVar();
}
// Fancy widget
ImGui::SeparatorText("Interactive Image Viewer");
static ExampleImageViewerData image_viewer;
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, my_tex_h * 2.0f);
ExampleImageViewer_DrawOptions(&image_viewer);
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, my_tex_id, (int)my_tex_w, (int)my_tex_h);
IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
ImGui::SeparatorText("Textured Buttons");
ImGui::TextWrapped("And now some textured buttons..");
static int pressed_count = 0;
for (int i = 0; i < 8; i++)
@@ -7821,6 +7897,8 @@ static void DemoWindowColumns()
// [SECTION] DemoWindowInputs()
//-----------------------------------------------------------------------------
#include "imgui_internal.h" // FIXME Until the new key owner/routing system are in public API this section of the demo needs internal (and is kept in a branch).
static void DemoWindowInputs()
{
if (ImGui::CollapsingHeader("Inputs & Focus"))
@@ -8006,7 +8084,353 @@ static void DemoWindowInputs()
}
ImGui::EndChild();
ImGui::PopStyleColor();
ImGui::TreePop();
}
// Ownership, Routings
IMGUI_DEMO_MARKER("Inputs & Focus/Key Ownership");
if (ImGui::TreeNode("Key Ownership"))
{
HelpMarker("See 'Tools->Metrics/Debugger->Inputs' to visualize ownership/routing data.");
// Demonstrate basic key ownership system
// Standard widgets all claim and test for key ownership
// (note that the ActiveId and HoveredId systems also generally prevents multiple items from interacting, but at a different level)
if (ImGui::TreeNode("1. Standard widgets taking input ownership"))
{
HelpMarker("Standard widgets claim and test for key ownership.\n\n\"Keys\" include mouse buttons, gamepad axises etc.");
const ImGuiKey key = ImGuiKey_MouseLeft; // Note how mouse and gamepad are also included in ImGuiKey: same data type for all.
const char* key_name = ImGui::GetKeyName(key);
ImGui::Text("Press '%s'", key_name);
ImGui::Text("1st read: (button)");
ImGui::Button("Click and Hold Me Tight!");
// Assume this is another piece of code running later.
// The *default* value for owner is ImGuiKeyOwner_Any, same as calling the simplified function:
// IsKeyDown(key) == IsKeyDown(key, ImGuiKeyOwner_Any)
// IsKeyPressed(key) == IsKeyPressed(key, ImGuiKeyOwner_Any)
// But notice the "bool repeat = true" parameter in old signature 'IsKeyPressed(key, repeat)'
// with the new signature becomes 'IsKeyPressed(key, owner, ImGuiInputFlags_Repeat)'
ImGui::Text("2nd read: (NOT owner-aware)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key) ? "PRESSED!" : "..");
ImGui::Text("3rd read: (owner-aware: ImGuiKeyOwner_NoOwner)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key, ImGuiKeyOwner_NoOwner) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) ? "PRESSED!" : "..");
ImGuiID another_owner = ImGui::GetID("AnotherItem");
ImGui::Text("4nd read: (owner-aware: different owner)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key, another_owner) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, ImGuiInputFlags_Repeat, another_owner) ? "PRESSED!" : "..");
ImGui::TreePop();
}
if (ImGui::TreeNode("2. Calling SetKeyOwner()"))
{
const ImGuiKey key = ImGuiKey_A;
const char* key_name = ImGui::GetKeyName(key);
ImGui::Text("Press '%s'", key_name);
ImGui::Text("1st read:");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, false) ? "PRESSED!" : "..");
ImGui::Text("...when pressed, call SetKeyOwner() with an owner ID.");
ImGuiID owner_1 = ImGui::GetID("MyItemID");
if (ImGui::IsKeyPressed(key, ImGuiInputFlags_Repeat, owner_1))
ImGui::SetKeyOwner(key, owner_1);
// Assume this is another piece of code running later.
// (same comments as in section 1)
ImGui::Text("2nd read: (NOT owner-aware)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key) ? "PRESSED!" : "..");
ImGui::Text("3rd read: (owner-aware: ImGuiKeyOwner_NoOwner)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key, ImGuiKeyOwner_NoOwner) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) ? "PRESSED!" : "..");
ImGuiID another_owner = ImGui::GetID("AnotherItem");
ImGui::Text("4th read: (owner-aware: different owner)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key, another_owner) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, ImGuiInputFlags_Repeat, another_owner) ? "PRESSED!" : "..");
ImGui::TreePop();
}
// Demonstrate using SetKeyOwner() with ImGuiInputFlags_LockThisFrame / ImGuiInputFlags_LockUntilRelease flags.
// - Using an owner id solves all/most cases as long as everyone is "owner-id-aware",
// meaning they call the long form of IsKeyXXX function. This is the preferred way to do things.
// - Using ImGuiInputFlags_LockXXXX flags is a way to prevent code that is NOT owner-id-aware from accessing the key.
// Think of it as "eating" a key completely: only same owner ID can access the key/button.
if (ImGui::TreeNode("3. Calling SetKeyOwner() with ImGuiInputFlags_LockXXX flags for non-owner-aware code"))
{
const ImGuiKey key = ImGuiKey_B;
const char* key_name = ImGui::GetKeyName(key);
ImGui::Text("Press '%s'", key_name);
static bool lock_this_frame = false;
static bool lock_until_release = false;
ImGui::Text("1st read:");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, false) ? "PRESSED!" : "..");
ImGui::Text("...when pressed, call SetKeyOwner() with:");
ImGui::Checkbox("ImGuiInputFlags_LockThisFrame", &lock_this_frame);
ImGui::Checkbox("ImGuiInputFlags_LockUntilRelease", &lock_until_release);
if (ImGui::IsKeyPressed(key, false) && (lock_this_frame || lock_until_release))
ImGui::SetKeyOwner(key, 0, (lock_this_frame ? ImGuiInputFlags_LockThisFrame : 0) | (lock_until_release ? ImGuiInputFlags_LockUntilRelease : 0));
// Assume this is another piece of code running later. The calls are not owner-aware,
// due to the lock they won't be able to see the key.
ImGui::Text("2nd read: (NOT owner-aware)");
ImGui::Text("- IsKeyDown(%s): %s", key_name, ImGui::IsKeyDown(key) ? "DOWN!" : "..");
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, false) ? "PRESSED!" : "..");
ImGui::TreePop();
}
// Miscellaneous examples
if (ImGui::TreeNode("Usage Scenarios"))
{
// We use colored buttons for the demo but this would generally apply to any widget.
const ImVec2 button_sz(60.0f, 60.0f);
const ImGuiColorEditFlags button_flags = ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop;
if (ImGui::TreeNode("1. Claiming Mouse Wheel"))
{
static float value1 = 0.0f;
ImGui::Text("%.2f", value1);
ImGui::SameLine();
HelpMarker("Hover button and use mouse wheel: window scrolling won't be activated.");
ImGui::ColorButton("Item1", ImVec4(0.4f, 0.4f, 0.8f, 1.0f), button_flags, button_sz);
if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY))
value1 += io.MouseWheel;
static float value2 = 0.0f;
ImGui::Text("%.2f", value2);
ImGui::SameLine();
HelpMarker("Hold button and use mouse wheel: window scrolling won't be activated.");
ImGui::ColorButton("Item2", ImVec4(0.4f, 0.4f, 0.8f, 1.0f), button_flags, button_sz);
if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY, ImGuiInputFlags_CondActive))
value2 += io.MouseWheel;
ImGui::TreePop();
}
if (ImGui::TreeNode("2. Claiming Alt key"))
{
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
static float spinner0 = 0.0f;
ImGui::Text("%.3f", spinner0);
ImGui::SameLine();
HelpMarker("Click, hold ALT drag to tweak value. Notice that Alt doesn't move focus to menu bar.");
ImGui::Button("Spin me", button_sz);
if (ImGui::IsItemActive())
{
ImGui::SetKeyOwner(ImGuiMod_Alt, ImGui::GetItemID());
if (ImGui::IsKeyDown(ImGuiMod_Alt)) // Poll on Active: we don't need to check for ownership of ImGuiMod_Alt since we know we unconditionally own it.
spinner0 += io.MouseDelta.x;
}
// When using of keys is conditioned by item being hovered or active,
// it creates a natural exclusivity, since only one item can be hovered or active.
// SetItemKeyOwner(...) is a shortcut for doing 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(..., GetItemID()); }'
static int value1 = 0;
ImGui::Text("%d", value1);
ImGui::SameLine();
HelpMarker("Item1 claims ALT key when Hovered or Active, counter increase when pressing ALT while Hovered.");
ImGui::Button("Item1", button_sz);
if (ImGui::SetItemKeyOwner(ImGuiMod_Alt)) // Claim Alt on Hover and Active
if (ImGui::IsItemHovered() && ImGui::IsKeyPressed(ImGuiMod_Alt, false)) // Poll on Hover: we don't need to check for ownership of ImGuiMod_Alt since we know we unconditionally own it.
value1++;
ImGui::TreePop();
}
// Routing options are only available for Shortcuts (not Key)
// Using shortcut functions with only ImGuiMod_Alt means that other modifiers e.g. CTRL+ALT+S won't be affected, which is often desirable.
// Here we use ImGuiInputFlags_RouteFocused which will claim the Alt shortcut when the window is focused.
// Notice that opening this node will claim Alt, therefore change the behavior of the key checks in section (2) above.
if (ImGui::TreeNode("3. Claiming Alt shortcut"))
{
// Using Shortcut() with ImGuiInputFlags_RouteFocused means we react when parent window is focused.
// - Passing 0 (== ImGuiKeyOwner_Any) means current location will be used to identify.
// As both calls are from the same location, both items will receive the shortcut.
// - Passing GetItemID() here means they both have their unique id,
// - Item2 will only receive the shortcut when parent window is focused.
// - Item3 will only receive the shortcut when active.
// Not passing an item id would use current location as id so both items will always receive shortcut.
static bool use_shared_owner = false;
ImGui::Checkbox("Item2 and Item3 use same owner/location", &use_shared_owner);
static int value2 = 0;
ImGui::Text("%d", value2);
ImGui::SameLine();
HelpMarker("Item2 reads ALT shortcut when its parent window is focused.");
ImGui::Button("Item2", button_sz);
if (ImGui::Shortcut(ImGuiMod_Alt, 0, use_shared_owner ? 0 : ImGui::GetItemID()))
value2++;
static int value3 = 0;
ImGui::Text("%d", value3);
ImGui::SameLine();
HelpMarker("Item3 reads ALT shortcut when its parent window is focused AND it is active. Therefore, only active previous button will get the shortcut");
ImGui::Button("Item3", button_sz);
if (ImGui::Shortcut(ImGuiMod_Alt, 0, use_shared_owner ? 0 : ImGui::GetItemID()))
value3++;
ImGui::TreePop();
}
if (ImGui::TreeNode("4. Claiming Home key globally"))
{
static bool enable_home_robbery = false;
static int home_presses = 0;
ImGui::Checkbox("Global steal ImGuiKey_Home", &enable_home_robbery);
ImGui::Text("Home presses: %d", home_presses);
if (enable_home_robbery)
{
// Claim ownership is enough to keep Key away from main library behavior or any owner-aware code.
// - We optionally use the ImGuiInputFlags_LockUntilRelease to keep key away from code that is not owner-aware,
// but Dear ImGui itself is so that's not technically needed (unless you are stealing from another piece of code).
ImGuiID robber_id = ImGui::GetID("Some Identifier");
ImGui::SetKeyOwner(ImGuiKey_Home, robber_id, ImGuiInputFlags_LockUntilRelease);
if (ImGui::IsKeyPressed(ImGuiKey_Home, ImGuiInputFlags_Repeat, robber_id)) // We unconditionally own the key so no need to test for ownership
home_presses++;
}
ImGui::TreePop();
}
if (ImGui::TreeNode("5. Claiming CTRL+A shortcut globally"))
{
// Using a priority of ImGuiInputFlags_RouteGlobal + RouteOverActive means we takes away even from an active item (e.g. InputText)
// This is better covered in "Shortcut Routing basics" above.
static bool enable_ctrl_a_robbery = false;
static int ctrl_a_presses = 0;
ImGui::Checkbox("Global steal CTRL+A", &enable_ctrl_a_robbery);
ImGui::Text("CTRL+A presses: %d", ctrl_a_presses);
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_A, enable_ctrl_a_robbery ? ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive : ImGuiInputFlags_RouteAlways))
ctrl_a_presses++;
ImGui::TreePop();
}
if (ImGui::TreeNode("6. Disable ESC key from InputText()"))
{
static char buf[9];
ImGui::InputText("Text", buf, IM_ARRAYSIZE(buf));
// - If you don't need to use the key, you can use 'owner_id=0', 'flags=ImGuiInputFlags_LockXXX'
// as a convenience to hide the key from everyone.
// - If you need to use the key yourself, you need to use any arbitrary ID, and then use this ID to read the key.
// e.g. ImGui::SetKeyOwner(ImGuiKey_Escape, ImGui::GetID("robber")); + later use same ID to access the key.
if (ImGui::IsItemActive())
ImGui::SetKeyOwner(ImGuiKey_Escape, 0, ImGuiInputFlags_LockUntilRelease);
ImGui::TreePop();
}
if (ImGui::TreeNode("7. Claiming ESC key away from InputText()"))
{
static char buf[9];
ImGui::InputText("Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_EscapeClearsAll);
if (ImGui::IsItemActive())
{
// Using a route which is higher priority than one claimed the ActiveId
ImGuiID robber_id = ImGui::GetID("robber");
if (ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, robber_id))
{
strcpy(buf, "Esc!");
ImGui::ClearActiveID();
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("8. Claiming ESC away from nav logic (e.g. exiting a child)"))
{
ImGui::BeginChild("child", ImVec2(-FLT_MIN, 50), true);
ImGui::Button("Button in child");
if (ImGui::IsWindowFocused())
ImGui::SetKeyOwner(ImGuiKey_Escape, ImGui::GetID("")); // any id
ImGui::EndChild();
ImGui::TreePop();
}
if (ImGui::TreeNode("9. Claiming Tab, CTRL+Tab"))
{
static int mode = 0;
static int counter = 0;
HelpMarker("Showcasing many variants as a recap.\nPlease read code and comments carefully!");
const char* mode_names[] = { "None", "Disable Tab key (item)", "Disable Tab key (global)", "Disable CTRL+Tab (global)", "Disable CTRL+Tab (if focused)", "Read CTRL+Tab (global)", "Replace CTRL+Tab (global)", "Replace CTRL+Tab (if focused)" };
ImGui::Combo("Operation Mode", &mode, mode_names, IM_ARRAYSIZE(mode_names));
ImGui::Text("Counter = %d", counter);
switch (mode)
{
case 1:
// Item take ownership of Tab key when hovered/active (meaning ALL uses of Tab will be disabled, not just CTRL+Tab)
ImGui::Button("This Button Steals The Tab Key");
ImGui::SetItemKeyOwner(ImGuiKey_Tab);
ImGui::SameLine();
HelpMarker("While hovering or activating this button, TAB key is stolen (e.g. won't tab out into other systems)");
break;
case 2:
// Take ownership of Tab key (meaning ALL uses of Tab will be disabled, not just CTRL+Tab)
ImGui::SetKeyOwner(ImGuiKey_Tab, ImGui::GetID("some-id"));
break;
case 3:
// Disable CTRL+Tab shortcuts (global): assign an owner to steal the route to our two shortcuts
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, 0, ImGui::GetID("some-id"));
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, 0, ImGui::GetID("some-id"));
break;
case 4:
// Disable CTRL+Tab shortcuts (if focused): assign an owner to steal the route to our two shortcuts, applies focus testing so will only apply if window is in focus chain
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteFocused, ImGui::GetID("some-id"));
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteFocused, ImGui::GetID("some-id"));
break;
case 5:
// Read CTRL+Tab (global): reading keys without interfering with any behaviors (need to specify ImGuiInputFlags_RouteAlways as other policies will interfere)
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteAlways, ImGuiKeyOwner_Any))
counter++;
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteAlways, ImGuiKeyOwner_Any))
counter--;
break;
case 6:
{
// Replace CTRL+Tab (global)
// - We steal the route and assign it to our ID (so core system won't access it). Our reading queries now need to specify that ID.
ImGuiID id = ImGui::GetID("My-Ctrl-Tab-Handler");
//ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, id, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive);
//ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, id, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive);
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, id))
counter++; // You could perform some other action here.
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, id))
counter--;
break;
}
case 7:
// Replace CTRL+Tab (if focused)
// - Passing ImGuiInputFlags_RouteFocused will test for focus and assign a route using a default owner id based on location (so we can use 0 as id)
// - This would also work if we replaced 0 with ImGui::GetID("My-Ctrl-Tab-Handler")
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab))
counter++; // You could perform some other action here.
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab))
counter--;
break;
}
static char buf[8] = "";
ImGui::InputTextWithHint("Dummy", "(dummy input text to test effect of Tabbing)", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop();
}
ImGui::TreePop();
}
ImGui::TreePop();
}
@@ -8827,7 +9251,7 @@ static void ShowExampleMenuFile()
IMGUI_DEMO_MARKER("Examples/Menu/Options");
static bool enabled = true;
ImGui::MenuItem("Enabled", "", &enabled);
ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Borders);
ImGui::BeginChild("child", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5.0f), ImGuiChildFlags_Borders);
for (int i = 0; i < 10; i++)
ImGui::Text("Scrolling Text %d", i);
ImGui::EndChild();
@@ -9239,6 +9663,28 @@ static void ShowExampleAppConsole(bool* p_open)
console.Draw("Example: Console", p_open);
}
//-----------------------------------------------------------------------------
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
//-----------------------------------------------------------------------------
static void ShowExampleAppImageViewer(bool* p_open)
{
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
ImTextureRef tex_ref = atlas->TexRef; // We don't have access to other textures in this demo!
int tex_w = atlas->TexData->Width;
int tex_h = atlas->TexData->Height;
if (ImGui::Begin("Example: Image Viewer", p_open))
{
static ExampleImageViewerData image_viewer;
ExampleImageViewer_DrawOptions(&image_viewer);
ImVec2 canvas_size = ImGui::GetContentRegionAvail();
ImVec2 canvas_min_size = ImGui::IsWindowAppearing() ? ImVec2(3.0f * tex_w, 4.0f * tex_h) : ImVec2(1.0f, 1.0f);
canvas_size = ImVec2(IM_MAX(canvas_size.x, canvas_min_size.x), IM_MAX(canvas_size.y, canvas_min_size.y));
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, tex_ref, tex_w, tex_h);
}
ImGui::End();
}
//-----------------------------------------------------------------------------
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
//-----------------------------------------------------------------------------
@@ -10131,20 +10577,20 @@ static void ShowExampleAppCustomRendering(bool* p_open)
draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, th); x += sz + spacing; // Square
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th); x += sz + spacing; // Square with all rounded corners
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th, corners_tl_br); x += sz + spacing; // Square with two rounded corners
draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
//draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th); x += sz + spacing; // Concave Shape
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, th, ImDrawFlags_Closed); x += sz + spacing; // Concave Shape
//draw_list->AddPolyline(concave_shape, IM_COUNTOF(concave_shape), col, ImDrawFlags_Closed, th);
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
draw_list->AddLineH(x, x + sz, y, col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
draw_list->AddLineV(x, y, y + sz, col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
// Path
draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
draw_list->PathStroke(col, ImDrawFlags_None, th);
draw_list->PathStroke(col, th);
x += sz + spacing;
// Quadratic Bezier Curve (3 control points)
@@ -10278,9 +10724,9 @@ static void ShowExampleAppCustomRendering(bool* p_open)
{
const float GRID_STEP = 64.0f;
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
draw_list->AddLineV(canvas_p0.x + x, canvas_p0.y, canvas_p1.y, IM_COL32(200, 200, 200, 40));
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
draw_list->AddLineH(canvas_p0.x, canvas_p1.x, canvas_p0.y + y, IM_COL32(200, 200, 200, 40));
}
for (int n = 0; n < points.Size; n += 2)
draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (drawing and font code)
/*
@@ -208,6 +208,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgHovered], 0.65f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
@@ -275,6 +276,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgActive], 0.65f);
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
@@ -343,6 +345,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_CheckboxSelectedBg] = ImVec4(0.95f, 0.97f, 1.00f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
@@ -811,7 +814,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, float thickness, ImDrawFlags flags)
{
if (points_count < 2 || (col & IM_COL32_A_MASK) == 0)
return;
@@ -820,6 +823,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > _FringeScale);
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?");
if (Flags & ImDrawListFlags_AntiAliasedLines)
{
@@ -1441,14 +1445,6 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr
{
if (rounding >= 0.5f)
{
// If this assert triggers on legacy code, please update your code replacing hardcoded values with ImDrawFlags_RoundCorners* values.
// - See details in 1.82 Changelog as well as 2021/03/12 and 2023/09/08 entries in "API BREAKING CHANGES" section.
// - Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc. anyway.
// - Marked obsolete in 1.82 and completely removed in 1.90:
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'
IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!");
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
flags |= ImDrawFlags_RoundCornersAll;
@@ -1481,20 +1477,48 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
return;
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
PathStroke(col, 0, thickness);
PathStroke(col, thickness);
}
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
PathLineTo(ImVec2(min_x + 0.5f, y + 0.5f)); // Same as AddLine() above.
PathLineTo(ImVec2(max_x + 0.5f, y + 0.5f));
PathStroke(col, thickness);
}
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
PathLineTo(ImVec2(x + 0.5f, min_y + 0.5f)); // Same as AddLine() above.
PathLineTo(ImVec2(x + 0.5f, max_y + 0.5f));
PathStroke(col, thickness);
}
// p_min = upper-left, p_max = lower-right
// Note we don't render 1 pixels sized rectangles properly.
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
{
// If this assert triggers on legacy code:
// - 1.92.8 (2025/04): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
// See "API BREAKING CHANGES" section for 1.82 and 1.90.
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
if ((col & IM_COL32_A_MASK) == 0)
return;
if (Flags & ImDrawListFlags_AntiAliasedLines)
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
else
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
PathStroke(col, ImDrawFlags_Closed, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
@@ -1538,7 +1562,7 @@ void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, c
PathLineTo(p2);
PathLineTo(p3);
PathLineTo(p4);
PathStroke(col, ImDrawFlags_Closed, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col)
@@ -1561,7 +1585,7 @@ void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p
PathLineTo(p1);
PathLineTo(p2);
PathLineTo(p3);
PathStroke(col, ImDrawFlags_Closed, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col)
@@ -1596,7 +1620,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
}
PathStroke(col, ImDrawFlags_Closed, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
@@ -1632,7 +1656,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
PathStroke(col, ImDrawFlags_Closed, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
// Guaranteed to honor 'num_segments'
@@ -1659,7 +1683,7 @@ void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 co
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
PathStroke(col, true, thickness);
PathStroke(col, thickness, ImDrawFlags_Closed);
}
void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments)
@@ -1684,7 +1708,7 @@ void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2
PathLineTo(p1);
PathBezierCubicCurveTo(p2, p3, p4, num_segments);
PathStroke(col, 0, thickness);
PathStroke(col, thickness);
}
// Quadratic Bezier takes 3 controls points
@@ -1695,7 +1719,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
PathLineTo(p1);
PathBezierQuadraticCurveTo(p2, p3, num_segments);
PathStroke(col, 0, thickness);
PathStroke(col, thickness);
}
void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
@@ -2495,10 +2519,11 @@ void ImTextureData::DestroyPixels()
// - Default texture data encoded in ASCII
// - ImFontAtlas()
// - ImFontAtlas::Clear()
// - ImFontAtlas::CompactCache()
// - ImFontAtlas::ClearFonts()
// - ImFontAtlas::ClearInputData()
// - ImFontAtlas::ClearTexData()
// - ImFontAtlas::ClearFonts()
// - ImFontAtlas::CompactCache()
// - ImFontAtlas::SetFontLoader()
//-----------------------------------------------------------------------------
// - ImFontAtlasUpdateNewFrame()
// - ImFontAtlasTextureBlockConvert()
@@ -2659,7 +2684,9 @@ ImFontAtlas::~ImFontAtlas()
TexData = NULL;
}
// If you call this mid-frame, you would need to add new font and bind them!
// You probably should not call this directly. It is not well specified.
// If you want to replace all your fonts mid-frame, most likely you should instead call ClearFonts() then load the new fonts.
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
void ImFontAtlas::Clear()
{
bool backup_renderer_has_textures = RendererHasTextures;
@@ -2669,20 +2696,27 @@ void ImFontAtlas::Clear()
RendererHasTextures = backup_renderer_has_textures;
}
void ImFontAtlas::CompactCache()
void ImFontAtlas::ClearFonts()
{
ImFontAtlasTextureCompact(this);
}
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
{
ImFontAtlasBuildSetupFontLoader(this, font_loader);
// FIXME-NEWATLAS: Illegal to remove currently bound font.
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFont* font : Fonts)
ImFontAtlasBuildNotifySetFont(this, font, NULL);
ImFontAtlasBuildDestroy(this);
ClearInputData();
Fonts.clear_delete();
TexIsBuilt = false;
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
if (shared_data->FontAtlas == this)
{
shared_data->Font = NULL;
shared_data->FontScale = shared_data->FontSize = 0.0f;
}
}
void ImFontAtlas::ClearInputData()
{
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFont* font : Fonts)
ImFontAtlasFontDestroyOutput(this, font);
for (ImFontConfig& font_cfg : Sources)
@@ -2706,22 +2740,14 @@ void ImFontAtlas::ClearTexData()
//Locked = true; // Hoped to be able to lock this down but some reload patterns may not be happy with it.
}
void ImFontAtlas::ClearFonts()
void ImFontAtlas::CompactCache()
{
// FIXME-NEWATLAS: Illegal to remove currently bound font.
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFont* font : Fonts)
ImFontAtlasBuildNotifySetFont(this, font, NULL);
ImFontAtlasBuildDestroy(this);
ClearInputData();
Fonts.clear_delete();
TexIsBuilt = false;
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
if (shared_data->FontAtlas == this)
{
shared_data->Font = NULL;
shared_data->FontScale = shared_data->FontSize = 0.0f;
}
ImFontAtlasTextureCompact(this);
}
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
{
ImFontAtlasBuildSetupFontLoader(this, font_loader);
}
static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* atlas)
@@ -2955,12 +2981,17 @@ void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, I
memcpy(dst_tex->GetPixelsAt(dst_x, dst_y + y), src_tex->GetPixelsAt(src_x, src_y + y), w * dst_tex->BytesPerPixel);
}
// Queue texture block update for renderer backend
void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h)
{
ImTextureDataQueueUpload(tex, x, y, w, h);
atlas->TexIsBuilt = false;
}
// Queue texture block update for renderer backend
void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h)
{
IM_ASSERT(tex->Status != ImTextureStatus_WantDestroy && tex->Status != ImTextureStatus_Destroyed);
IM_ASSERT(x >= 0 && x <= 0xFFFF && y >= 0 && y <= 0xFFFF && w >= 0 && x + w <= 0x10000 && h >= 0 && y + h <= 0x10000);
IM_UNUSED(atlas);
ImTextureRect req = { (unsigned short)x, (unsigned short)y, (unsigned short)w, (unsigned short)h };
int new_x1 = ImMax(tex->UpdateRect.w == 0 ? 0 : tex->UpdateRect.x + tex->UpdateRect.w, req.x + req.w);
@@ -2973,7 +3004,6 @@ void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex,
tex->UsedRect.y = ImMin(tex->UsedRect.y, req.y);
tex->UsedRect.w = (unsigned short)(ImMax(tex->UsedRect.x + tex->UsedRect.w, req.x + req.w) - tex->UsedRect.x);
tex->UsedRect.h = (unsigned short)(ImMax(tex->UsedRect.y + tex->UsedRect.h, req.y + req.h) - tex->UsedRect.y);
atlas->TexIsBuilt = false;
// No need to queue if status is == ImTextureStatus_WantCreate
if (tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantUpdates)
@@ -6019,7 +6049,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float
draw_list->PathLineTo(ImVec2(bx - third, by - third));
draw_list->PathLineTo(ImVec2(bx, by));
draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f));
draw_list->PathStroke(col, 0, thickness);
draw_list->PathStroke(col, thickness);
}
// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (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.
@@ -1005,6 +1005,7 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
ImGuiItemStatusFlags_EditedInternal = 1 << 11, // Similar to ImGuiItemStatusFlags_Edited but bypassing ImGuiItemFlags_NoMarkEdited.
// Additional status + semantic for ImGuiTestEngine
#ifdef IMGUI_ENABLE_TEST_ENGINE
@@ -1210,6 +1211,7 @@ struct IMGUI_API ImGuiMenuColumns
};
// Internal temporary state for deactivating InputText() instances.
// Store as part of ImGuiDeactivatedItemData?
struct IMGUI_API ImGuiInputTextDeactivatedState
{
ImGuiID ID; // widget id owning the text state (which just got deactivated)
@@ -1455,6 +1457,7 @@ struct ImGuiPtrOrIndex
};
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
// Also see ImGuiInputTextDeactivatedState which is an extension for this for InputText()
struct ImGuiDeactivatedItemData
{
ImGuiID ID;
@@ -3214,7 +3217,7 @@ namespace ImGui
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
// Fonts, drawing
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL: DO NOT USE YET.
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL.
IMGUI_API void UnregisterUserTexture(ImTextureData* tex);
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
@@ -3435,7 +3438,7 @@ namespace ImGui
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags);
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
@@ -3493,7 +3496,7 @@ namespace ImGui
IMGUI_API void ClearDragDrop();
IMGUI_API bool IsDragDropPayloadBeingAccepted();
IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb);
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb);
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding);
// Typing-Select API
// (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature)
@@ -3976,6 +3979,7 @@ IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex,
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
IMGUI_API const char* ImTextureDataGetFormatName(ImTextureFormat format);

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (tables and columns code)
/*
@@ -2074,11 +2074,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
// Draw top border
if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), top_border_col, border_size);
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y1, top_border_col, border_size);
// Draw bottom border at the row unfreezing mark (always strong)
if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y2, table->BorderColorStrong, border_size);
}
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
@@ -2855,7 +2855,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0)
draw_y2 = draw_y2_body;
if (draw_y2 > draw_y1)
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size);
inner_drawlist->AddLineV(column->MaxX, draw_y1, draw_y2, TableGetColumnBorderCol(table, order_n, column_n), border_size);
}
}
@@ -2872,17 +2872,17 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
const ImU32 outer_col = table->BorderColorStrong;
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
{
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, border_size);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
{
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
inner_drawlist->AddLineV(outer_border.Min.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
inner_drawlist->AddLineV(outer_border.Max.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
{
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Min.y, outer_col, border_size);
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Max.y, outer_col, border_size);
}
}
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
@@ -2890,7 +2890,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
// Draw bottom-most row border between it is above outer border.
const float border_y = table->RowPosY2;
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
inner_drawlist->AddLineH(table->BorderX1, table->BorderX2, border_y, table->BorderColorLight, border_size);
}
inner_drawlist->PopClipRect();
@@ -4618,7 +4618,7 @@ void ImGui::EndColumns()
// Draw column
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
const float xi = IM_TRUNC(x);
window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
window->DrawList->AddLineV(xi, y1 + 1.0f, y2, col);
}
// Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.

View File

@@ -1,4 +1,4 @@
// dear imgui, v1.92.8 WIP
// dear imgui, v1.92.8
// (widgets code)
/*
@@ -1151,7 +1151,7 @@ void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const Im
else
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
if (g.Style.ImageBorderSize > 0.0f)
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, ImDrawFlags_None, g.Style.ImageBorderSize);
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, g.Style.ImageBorderSize);
}
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
@@ -1288,8 +1288,9 @@ bool ImGui::Checkbox(const char* label, bool* v)
if (is_visible)
{
RenderNavCursor(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : (mixed_value || checked) ? ImGuiCol_CheckboxSelectedBg : ImGuiCol_FrameBg);
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
RenderFrame(check_bb.Min, check_bb.Max, bg_col, true, style.FrameRounding);
if (mixed_value)
{
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
@@ -1556,7 +1557,7 @@ bool ImGui::TextLink(const char* label)
}
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), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
window->DrawList->AddLineH(bb.Min.x, 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));
RenderText(bb.Min, label, label_end, false);
@@ -1766,9 +1767,9 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
const float sep1_x2 = label_pos.x - style.ItemSpacing.x;
const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x;
if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep1_x2, seps_y), separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness);
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness);
if (g.LogEnabled)
LogSetNextTextDecoration("---", NULL);
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
@@ -1778,7 +1779,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
if (g.LogEnabled)
LogText("---");
if (separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness);
}
}
@@ -2375,12 +2376,17 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
// Sanitize format
// - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
// - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %.
char format_sanitized[32];
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
{
format = type_info->ScanFmt;
}
else
{
format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_COUNTOF(format_sanitized));
if (format[0] == '\0')
format = type_info->ScanFmt; // Format doesn't want us to show the number currently, but we still need to parse the resulting input
}
// Small types need a 32-bit buffer to receive the result from scanf()
int v32 = 0;
@@ -3566,7 +3572,8 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
// - ImParseFormatSanitizeForPrinting() [Internal]
// - ImParseFormatSanitizeForScanning() [Internal]
// - ImParseFormatPrecision() [Internal]
// - TempInputTextScalar() [Internal]
// - TempInputText() [Internal]
// - TempInputScalar() [Internal]
// - InputScalar()
// - InputScalarN()
// - InputFloat()
@@ -3795,7 +3802,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
//IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
if (format == NULL)
format = DataTypeGetInfo(data_type)->PrintFmt;
@@ -3832,7 +3839,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
}
// Apply
bool value_changed = ret ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
bool value_changed = input_edited ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
// Step buttons
if (has_step_buttons)
@@ -3846,13 +3854,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
if (ButtonEx("-", ImVec2(button_size, button_size)))
{
DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
value_changed = true;
value_changed = ret = true;
}
SameLine(0, style.ItemInnerSpacing.x);
if (ButtonEx("+", ImVec2(button_size, button_size)))
{
DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
value_changed = true;
value_changed = ret = true;
}
PopItemFlag();
if (flags & ImGuiInputTextFlags_ReadOnly)
@@ -3874,6 +3882,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
if (value_changed)
MarkItemEdited(g.LastItemData.ID);
if (flags & ImGuiInputTextFlags_EnterReturnsTrue)
return ret;
return value_changed;
}
@@ -4574,6 +4584,7 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
ImGuiInputTextState* state = &g.InputTextState;
if (id == 0 || state->ID != id)
return;
//IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id);
g.InputTextDeactivatedState.ID = state->ID;
if (state->Flags & ImGuiInputTextFlags_ReadOnly)
{
@@ -4889,7 +4900,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
const bool is_osx = io.ConfigMacOSXBehaviors;
if (g.ActiveId != id && init_make_active)
if (init_make_active && g.ActiveId != id)
{
IM_ASSERT(state && state->ID == id);
SetActiveID(id, window);
@@ -5630,7 +5641,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);
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))
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)
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, 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.)
// This is required for some backends (SDL3) to start emitting character/text inputs.
@@ -6344,7 +6355,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
const int vert_start_idx = draw_list->VtxBuffer.Size;
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
draw_list->PathStroke(col_white, 0, wheel_thickness);
draw_list->PathStroke(col_white, wheel_thickness);
const int vert_end_idx = draw_list->VtxBuffer.Size;
// Paint colors over existing vertices
@@ -6488,7 +6499,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (g.Style.FrameBorderSize > 0.0f)
RenderFrameBorder(bb.Min, bb.Max, rounding);
else
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
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
}
// Drag and Drop Source
@@ -7161,11 +7172,11 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
if (x1 < x2)
window->DrawList->PathLineTo(ImVec2(x2, y));
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), ImDrawFlags_None, g.Style.TreeLinesSize);
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
else
{
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
window->DrawList->AddLineH(x1, x2, y, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
}
@@ -7191,7 +7202,7 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
float x = ImTrunc(data->DrawLinesX1);
if (data->DrawLinesTableColumn != -1)
TablePushColumnChannel(data->DrawLinesTableColumn);
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
window->DrawList->AddLineV(x, y1, y2, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
if (data->DrawLinesTableColumn != -1)
TablePopColumnChannel();
}
@@ -8364,11 +8375,23 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
if (ImGuiTable* table = g.CurrentTable)
if (table->CurrentColumn != -1)
{
// FIXME: We cannot use current ClipRect as it includes HostClipRect.
// A more generic version would be nice, but window->WorkRect.Min/Max exclude CellPadding. (#7994)
// FIXME: We cannot solely use current ClipRect as it includes HostClipRect.
// However we account for ClipRect being larger than current column (e.g. when using SpanAllColumns)
// A more generic version would be nice, but window->WorkRect.Min/Max exclude CellPadding. (#7994, #9383)
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
item_rect.Min.x = ImMax(item_rect.Min.x, column->MinX);
item_rect.Max.x = ImMin(item_rect.Max.x, column->MaxX);
float clip_min_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Min.x : window->ClipRect.Min.x;
float clip_max_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Max.x : window->ClipRect.Max.x;
if (clip_min_x != clip_max_x) // When zero sized we expect that bounds have been clamped and thus are unreliable
{
item_rect.Min.x = ImMax(item_rect.Min.x, ImMin(column->MinX, clip_min_x));
item_rect.Max.x = ImMin(item_rect.Max.x, ImMax(column->MaxX, clip_max_x));
}
else
{
item_rect.Min.x = ImMax(item_rect.Min.x, column->MinX);
item_rect.Max.x = ImMin(item_rect.Max.x, column->MaxX);
}
//GetForegroundDrawList()->AddRect(item_rect.Min, item_rect.Max, IM_COL32(255, 0, 255, 255));
}
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(item_rect);
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(item_rect);
@@ -9370,8 +9393,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
bool pressed;
// 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_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
@@ -9409,6 +9431,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (!enabled)
EndDisabled();
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
{
ClearActiveID();
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
}
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
if (menuset_is_open)
PopItemFlag();
@@ -9489,6 +9519,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
PopID();
if (g.ActiveId == id && want_open)
g.ActiveIdNoClearOnFocusLoss = true;
if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{
// Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame.
@@ -9581,7 +9614,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
BeginDisabled();
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
@@ -9624,6 +9657,17 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
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);
}
}
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
const ImGuiID id = g.LastItemData.ID;
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
{
ClearActiveID();
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
}
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
if (!enabled)
EndDisabled();
@@ -10736,7 +10780,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
float rounding = style.TabRounding;
display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9);
display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11);
display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize);
display_draw_list->PathStroke(overline_col, style.TabBarOverlineSize);
}
else
{
@@ -10840,7 +10884,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), g.Style.TabBorderSize);
}
}