Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_metal.mm
#	backends/imgui_impl_vulkan.cpp
#	imgui.cpp
This commit is contained in:
ocornut 2026-10-07 19:11:40 +02:00
commit 0cb6f6501c
12 changed files with 2793 additions and 696 deletions

View File

@ -18,6 +18,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-XX-XX: Metal: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-10-06: Added support for render passes with multiple color attachments: we render to the first one and leave the others untouched. (#9574)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-06: Metal: fixed resizing windows losing framebuffer scale. (#6828, #8856)
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
@ -67,14 +68,16 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows();
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
@end
#define IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS 8 // Metal's limit (see Metal Feature Set Tables). Not configurable.
// An object that encapsulates the data necessary to uniquely identify a
// render pipeline state. These are used as cache keys.
@interface FramebufferDescriptor : NSObject<NSCopying>
@property (nonatomic, assign) unsigned long sampleCount;
@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor*)renderPassDescriptor;
- (MTLPixelFormat)colorPixelFormatAtIndex:(NSUInteger)index;
@end
@interface MetalTexture : NSObject
@ -645,23 +648,33 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
#pragma mark - FramebufferDescriptor implementation
@implementation FramebufferDescriptor
{
MTLPixelFormat _colorPixelFormats[IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS];
}
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor*)renderPassDescriptor
{
if ((self = [super init]))
{
_sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
_colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
for (NSUInteger n = 0; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++)
_colorPixelFormats[n] = renderPassDescriptor.colorAttachments[n].texture.pixelFormat;
_depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
_stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat;
}
return self;
}
- (MTLPixelFormat)colorPixelFormatAtIndex:(NSUInteger)index
{
return _colorPixelFormats[index];
}
- (nonnull id)copyWithZone:(nullable NSZone*)zone
{
FramebufferDescriptor* copy = [[FramebufferDescriptor allocWithZone:zone] init];
copy.sampleCount = self.sampleCount;
copy.colorPixelFormat = self.colorPixelFormat;
memcpy(copy->_colorPixelFormats, _colorPixelFormats, sizeof(_colorPixelFormats));
copy.depthPixelFormat = self.depthPixelFormat;
copy.stencilPixelFormat = self.stencilPixelFormat;
return copy;
@ -670,10 +683,12 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
- (NSUInteger)hash
{
NSUInteger sc = _sampleCount & 0x3;
NSUInteger cf = _colorPixelFormat & 0x3FF;
NSUInteger cf = _colorPixelFormats[0] & 0x3FF;
NSUInteger df = _depthPixelFormat & 0x3FF;
NSUInteger sf = _stencilPixelFormat & 0x3FF;
NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc;
for (NSUInteger n = 1; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++)
hash = hash * 31 + _colorPixelFormats[n];
return hash;
}
@ -683,7 +698,7 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
if (![other isKindOfClass:[FramebufferDescriptor class]])
return NO;
return other.sampleCount == self.sampleCount &&
other.colorPixelFormat == self.colorPixelFormat &&
memcmp(other->_colorPixelFormats, _colorPixelFormats, sizeof(_colorPixelFormats)) == 0 &&
other.depthPixelFormat == self.depthPixelFormat &&
other.stencilPixelFormat == self.stencilPixelFormat;
}
@ -829,7 +844,7 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
pipelineDescriptor.fragmentFunction = fragmentFunction;
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
pipelineDescriptor.rasterSampleCount = self.framebufferDescriptor.sampleCount;
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
pipelineDescriptor.colorAttachments[0].pixelFormat = [self.framebufferDescriptor colorPixelFormatAtIndex:0];
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
@ -837,6 +852,11 @@ static void ImGui_ImplMetal_InvalidateDeviceObjectsForPlatformWindows()
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
for (NSUInteger n = 1; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++) // Don't write to other color attachments, if any.
{
pipelineDescriptor.colorAttachments[n].pixelFormat = [self.framebufferDescriptor colorPixelFormatAtIndex:n];
pipelineDescriptor.colorAttachments[n].writeMask = MTLColorWriteMaskNone;
}
pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;

View File

@ -21,6 +21,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-10-06: Added support for render passes with multiple color attachments: we render to the first one and leave the others untouched. (#9574)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-08-06: Metal 4: fixed resizing windows losing framebuffer scale. (#6828, #8856)
// 2026-07-07: Metal 4: Added metal-cpp support. (#9461)
@ -59,14 +60,16 @@ struct ImGui_Metal4_ConstantData
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
@end
#define IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS 8 // Metal's limit (see Metal Feature Set Tables). Not configurable.
// An object that encapsulates the data necessary to uniquely identify a
// render pipeline state. These are used as cache keys.
@interface FramebufferDescriptor : NSObject<NSCopying>
@property (nonatomic, assign) unsigned long sampleCount;
@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor;
- (MTLPixelFormat)colorPixelFormatAtIndex:(NSUInteger)index;
@end
@interface MetalTexture : NSObject
@ -567,23 +570,33 @@ void ImGui_ImplMetal4_Shutdown()
#pragma mark - FramebufferDescriptor implementation
@implementation FramebufferDescriptor
{
MTLPixelFormat _colorPixelFormats[IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS];
}
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor
{
if ((self = [super init]))
{
_sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
_colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
for (NSUInteger n = 0; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++)
_colorPixelFormats[n] = renderPassDescriptor.colorAttachments[n].texture.pixelFormat;
_depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
_stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat;
}
return self;
}
- (MTLPixelFormat)colorPixelFormatAtIndex:(NSUInteger)index
{
return _colorPixelFormats[index];
}
- (nonnull id)copyWithZone:(nullable NSZone*)zone
{
FramebufferDescriptor* copy = [[FramebufferDescriptor allocWithZone:zone] init];
copy.sampleCount = self.sampleCount;
copy.colorPixelFormat = self.colorPixelFormat;
memcpy(copy->_colorPixelFormats, _colorPixelFormats, sizeof(_colorPixelFormats));
copy.depthPixelFormat = self.depthPixelFormat;
copy.stencilPixelFormat = self.stencilPixelFormat;
return copy;
@ -592,10 +605,12 @@ void ImGui_ImplMetal4_Shutdown()
- (NSUInteger)hash
{
NSUInteger sc = _sampleCount & 0x3;
NSUInteger cf = _colorPixelFormat & 0x3FF;
NSUInteger cf = _colorPixelFormats[0] & 0x3FF;
NSUInteger df = _depthPixelFormat & 0x3FF;
NSUInteger sf = _stencilPixelFormat & 0x3FF;
NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc;
for (NSUInteger n = 1; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++)
hash = hash * 31 + _colorPixelFormats[n];
return hash;
}
@ -605,7 +620,7 @@ void ImGui_ImplMetal4_Shutdown()
if (![other isKindOfClass:[FramebufferDescriptor class]])
return NO;
return other.sampleCount == self.sampleCount &&
other.colorPixelFormat == self.colorPixelFormat &&
memcmp(other->_colorPixelFormats, _colorPixelFormats, sizeof(_colorPixelFormats)) == 0 &&
other.depthPixelFormat == self.depthPixelFormat &&
other.stencilPixelFormat == self.stencilPixelFormat;
}
@ -761,7 +776,7 @@ fragment half4 fragment_main(VertexOut in [[stage_in]],
pipelineDescriptor.fragmentFunction = fragmentFunction;
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
pipelineDescriptor.rasterSampleCount = self.framebufferDescriptor.sampleCount;
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
pipelineDescriptor.colorAttachments[0].pixelFormat = [self.framebufferDescriptor colorPixelFormatAtIndex:0];
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
@ -769,6 +784,11 @@ fragment half4 fragment_main(VertexOut in [[stage_in]],
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
for (NSUInteger n = 1; n < IMGUI_IMPL_METAL_MAX_COLOR_ATTACHMENTS; n++) // Don't write to other color attachments, if any.
{
pipelineDescriptor.colorAttachments[n].pixelFormat = [self.framebufferDescriptor colorPixelFormatAtIndex:n];
pipelineDescriptor.colorAttachments[n].writeMask = MTLColorWriteMaskNone;
}
pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;

View File

@ -29,6 +29,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-10-06: Added support for dynamic rendering with multiple color attachments (PipelineRenderingCreateInfo.colorAttachmentCount > 1): we render to the first one and leave the others untouched. (#9574)
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-09-03: Added for support for multiple Vulkan contexts with custom loaders. (#6616)
// 2026-07-15: [Docking] Vulkan: fixed use-after-free when using multi-viewport with dynamic rendering path: deep-copy SurfaceFormat.format into the persistent buffer instead of storing a pointer to the viewport's wd->SurfaceFormat which dangles after the viewport is destroyed. (#9390, #9468)
@ -1094,7 +1095,14 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState color_attachment[1] = {};
// Blend into the first color attachment. With dynamic rendering, other color attachments of the rendering are left untouched (requires independentBlend feature).
int color_attachment_count = 1;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (bd->VulkanInitInfo.UseDynamicRendering && info->PipelineRenderingCreateInfo.colorAttachmentCount > 1)
color_attachment_count = (int)info->PipelineRenderingCreateInfo.colorAttachmentCount;
#endif
ImVector<VkPipelineColorBlendAttachmentState> color_attachment;
color_attachment.resize(color_attachment_count, VkPipelineColorBlendAttachmentState()); // colorWriteMask = 0
color_attachment[0].blendEnable = VK_TRUE;
color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
@ -1109,8 +1117,8 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc
VkPipelineColorBlendStateCreateInfo blend_info = {};
blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
blend_info.attachmentCount = 1;
blend_info.pAttachments = color_attachment;
blend_info.attachmentCount = (uint32_t)color_attachment.Size;
blend_info.pAttachments = color_attachment.Data;
ImVector<VkDynamicState> dynamic_states = info->ExtraDynamicStates;
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);

View File

@ -108,6 +108,7 @@ struct ImGui_ImplVulkan_PipelineInfo
// - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
// - About dynamic rendering:
// - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.
// - PipelineRenderingCreateInfo may describe multiple color attachments: we render to the first one and leave the others untouched. This requires the 'independentBlend' device feature.
struct ImGui_ImplVulkan_InitInfo
{
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)

View File

@ -39,8 +39,138 @@ HOW TO UPDATE?
VERSION 1.93.0 WIP (In Progress)
-----------------------------------------------------------------------
In 1.93.0, the `ImDrawList` rendering API has been improved to be more robust and
more consistent over the whole range of shapes. The rendering now matches much closer
to common vector drawing APIs, like html canvas. Improvements, like anti-aliased line
endings and stroke position were added. The coordinates passed to the API are now
consistently describing shape outlines.
For code using custom rendering: some details are now rendered slightly differently
(even if generally more consistent). The difference in rendering is in the range of
half a pixel, but that can lead to issues like some lines now look blurrier or more
transparent. All Dear ImGui widgets should appear identical or better.
The rendering of common shapes was optimized when the shapes fall on integer coordinates
(which is most of the UI). This includes skipping anti-aliasing when not needed, or
using textures instead of tessellated geometry to draw round corners.
The varying code-paths are designed to look indistinguishable from each others.
New rendering code fixes some inconsistencies between graphics APIs (e.g. DirectX vs OpenGL)
which are using different diamond exits rules.
New code should work precisely the same regardless of graphics API.
(note that using _StrokeLegacy mode can lead to similar inconsistencies)
New rendering code also deals better with animating thickness and rounding
(integer values are recommended).
While the current version doesn't make lots of visible use of the new features and
facilities, they are among the pillars that will make it easier to create prettier
contents, both for custom rendering and future versions of the library.
Use `ImDrawFlags_StrokeLegacy` mode to emulate old rendering:
- Per-primitive: draw_list->AddLine(..., ..., ImDrawFlags_StrokeLegacy);
- For a given scope: draw_list->PushDrawFlag(ImDrawFlags_StrokeLegacy, true); draw_list->AddLine(...); draw_list->PopDrawFlag();
- Globally: ImGui::Checkbox("DefaultsToStrokeLegacy", &io.ConfigDebugDrawListDefaultsToStrokeLegacy); // Map to a checkbox
- Globally: io.ConfigDebugDrawListDefaultsToStrokeLegacy = io.KeyShift; // Map on Shift
Main work courtesy of @memononen.
Additional work/reviewing/guidance by @ocornut.
With legacy bits from @thedmd, @potocpav.
Refer to our guides:
- ImDrawList Vector Rendering Reference
https://github.com/ocornut/imgui/wiki/Draw-List
(includes a precise list of differences between 1.92.9 and 1.93.0).
- ImDrawList 1.92.9 vs 1.93.0 Interactive Testbed
https://www.dearimgui.com/docs/drawlist_v193
(interactively discuss and compare differences between 1.92.9 and 1.93.9)
(downloadable HTML file, may be used offline)
- Pixel Perfect Anti-aliased Rendering
https://github.com/ocornut/imgui/wiki/Pixel-Perfect-Rendering
- How Anti-aliased Polyline Rendering is Implemented
https://github.com/ocornut/imgui/wiki/Polyline-Rendering
- Main topic:
https://github.com/ocornut/imgui/issues/9504
(if you have a problem to discuss, please open a new issue)
Breaking Changes:
- DrawList:
- AddLine(): removed the (+0.5f,+0.5f) offset that was sneakily added to input coordinates. (#9504)
- This fixes inconsistencies in the API and matches the PathXXX API.
- By default, stroke thickness extends on both side of the given segment.
e.g for a "pixel-perfect" looking line with thickness=1.0f, coords should be passed as center of each ends of the line.
- Use `ImDrawFlags_StrokeLegacy` to use old offset if required. Or you can apply the offset manually!
- Generally better, simple and faster to use `AddLineH()`, `AddLineV()` functions added in 1.92.8.
READ IF YOU ARE MINDFUL OF PIXEL-PERFECTNESS IN YOUR CUSTOM RENDERING/WIDGETS:
- TRANSITION GUIDE FOR AXIS-ALIGNED LINES:
- When switching from legacy `AddLine()` values to `AddLineV()`, `AddLineH()` you can keep same inputs coordinates as before:
- Old `AddLine({x, y1}, {x, y2}, col)` --> `AddLineV(x, y1, y2, col);` // Vertical line.
- Old `AddLine({x1, y}, {x2, y}, col)` --> `AddLineH(x1, x2, y, col);` // Horizontal line.
- This will be equivalent and faster for thickness=1.0f lines.
- Since `AddLine()` use default stroke pos Center and `AddLineV()`, `AddLineH()` use Inside, thickness>1.0f strokes will differ.
Using `ImDrawFlags_StrokeCenter` will match old result more closely (aka look centered),
but is more likely to look blurry as it already did before.
- Read table below about StrokePos and the "Pixel-Perfect Rendering" guide if you care about pixel-perfect lines.
- TRANSITION GUIDE FOR DIAGONAL LINES:
- Your lines will appear offset by -0.5f pixels on each axis.
Being anti-aliased diagonal lines, they won't look particularly better or worse, just slightly offset.
It'll likely only be noticeable if you carefully combined them with other primitives for a pixel-perfect result.
- Old `AddLine({x1, y1}, {x2, y2}, col)` --> `AddLine({x1 + 0.5f, y1 + 0.5f}, {x2+ 0.5f, y2 + 0.5f}, col);` // Same
or use `ImDrawFlags_StrokeLegacy` --> `AddLine({x1, y1}, {x2, y2}, col, thickness, ImDrawFlags_StrokeLegacy); // Offset by +0.5f + disable AA ends.
This reapplies the old offset, and should get you exactly the same result you previously
got for thickness=1.0f lines. But said result were previously sometimes ambiguous and
renderer-dependent. (#3116, #3258, #2441)
- Old code did not support anti-aliased ends, which could create gaps when rendering shapes out
of multiple contiguous lines instead of using `AddPolyline()`. There is a possibility that you
legacy code added fudge offsets here and there; which may not be necessary anymore if you use
`_AALineEnds`, or if you combine rendering of contiguous lines using `AddPolyline()`.
- AddRect(), AddCircle(), AddNgon(), AddEllipse(), AddTriangle(), AddQuad(): defaulting to "inside" stroke.
- All closed shapes with thickness=1.0f will appear identical.
- The difference for thickness>1.0f shapes may be minimal since very large strokes
were not well supported for widgets, but stroke will default inside widgets.
- AddCircle(), AddNgon(): removed +0.5f offset added to radius.
- This fixes inconsistencies in the API.
- Use `ImDrawFlags_StrokeLegacy` to use old method if required. Or you can apply the offset manually!
- AddRectFilled(): non-integer coordinates will now display anti-aliased edges.
Previously, non-integer coordinates rendered with aliased edges snapped by the
rasterizer. (#6971)
- AddRect(), AddRectFilled(): rectangles with inverted coordinates won't be visible
unless using ImDrawList_StrokeLegacy mode. With inverted coordinates (min > max):
- Legacy `AddRect()` rounding off -> visible but incorrect outer size.
- Legacy `AddRect()` rounding on -> visible but very glitchy.
- Legacy `AddRectFilled()` rounding off -> visible and correct.
- Legacy `AddRectFilled()` rounding on -> visible but very glitchy.
- Use `ImDrawFlags_StrokeLegacy` to use old rendering for cases without rounding, or fix coordinates.
- Merged `ImDrawListFlags` into `ImDrawFlags`. `ImDrawListFlags` was rarely used directly
and generally setup by the ImGui context. Keep inline redirection enums (will obsolete).
- `ImDrawListFlags_AntiAliasedLines` -> `ImDrawFlags_AALines`
- `ImDrawListFlags_AntiAliasedFill` -> `ImDrawFlags_AAFill`
- `ImDrawListFlags_AllowVtxOffset` -> `ImDrawFlags_UseVtxOffset`
- `ImDrawListFlags_TextNoPixelSnap` -> `ImDrawFlags_TextNoPixelSnap`
Unifying them allows easily using them for both per-primitives and scope alterations.
Kept redirection enums (will obsolete).
- Renamed all `ImDrawFlags_RoundCornersXXX` flags to `ImDrawFlags_RoundXXX`.
- `ImDrawFlags_RoundCornersAll` -> `ImDrawFlags_RoundAll`
- `ImDrawFlags_RoundCornersNone` -> `ImDrawFlags_RoundNone`
- `ImDrawFlags_RoundCornersTopLeft` -> `ImDrawFlags_RoundTopLeft`
- `ImDrawFlags_RoundCornersTopRight` -> `ImDrawFlags_RoundTopRight`
- `ImDrawFlags_RoundCornersBottomLeft` -> `ImDrawFlags_RoundBottomLeft`
- `ImDrawFlags_RoundCornersBottomRight` -> `ImDrawFlags_RoundBottomRight`
- `ImDrawFlags_RoundCornersTop` -> `ImDrawFlags_RoundTop`
- `ImDrawFlags_RoundCornersBottom` -> `ImDrawFlags_RoundBottom`
- `ImDrawFlags_RoundCornersLeft` -> `ImDrawFlags_RoundLeft`
- `ImDrawFlags_RoundCornersRight` -> `ImDrawFlags_RoundRight`
Kept redirection enums (will obsolete).
- Marked `ImDrawListFlags_AntiAliasedLinesUseTex` and `style.AntiAliasedLinesUseTex` as
obsolete, as the new line rendering code always uses textures.
- Enabling `ImFontAtlasFlags_NoBakedLines` in the font atlas will now disable support for
anti-aliased lines by clearing `style.AntiAliasedLines`/`style.AntiAliasedLineEnds`.
- Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in
favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit. It is
easier to tweak + this allows us to easily scale error threshold on high density screens.
@ -57,8 +187,127 @@ Breaking Changes:
sub-optimal and not reliable on some setup. Use `ImGui_ImplOpenGL3_SetClipOrigin(0)`
to enable auto-detection, or e.g. `ImGui_ImplOpenGL3_SetClipOrigin(GL_UPPER_LEFT)`.
Other Changes:
- DrawList:
- Added flags to specify stroke position in all `ImDrawList` stroking functions: (#9504) [@memononen]
- `ImDrawFlags_StrokeInside` (default for Rect, Circle/Ellipse, Triangle, Quad, Ngon + AddLineH, AddLineV)
- `ImDrawFlags_StrokeCenter` (default for Line, Polyline, Beziers, Paths function)
- `ImDrawFlags_StrokeCenterBiased` (center w/ bias for pixel perfect alignment)
- `ImDrawFlags_StrokeOutside`
- `ImDrawFlags_StrokeLegacy` (match old behavior)
- Legacy mode may be set as default for a given scope using `PushDrawFlag(ImDrawFlags_StrokeLegacy, true)`.
- Legacy code was generally applying +0.50f offsets which meant that,
- with thickness=1.0f: the stroke would appear inside.
- with thickness>1.0f: the stroke would start expanding on both sides but starting from that small initial offset.
- with thickness>1.0f for even integer values, the stroke would look blurry.
- TL;DR; the logic didn't make much sense for thickness>1.0f.
- Defaulting to Inside for closed shapes ensure that rectangles and lines are
never blurry, regardless of thickness, as long as input coordinates/sizes
are integers. (#9359) Recap:
------------------------------------------------------------------------
Thickness Legacy Inside Outside Center CenterBiased
------------------------------------------------------------------------
1.0f sharp sharp sharp blurry sharp
2.0f blurry sharp sharp sharp sharp
3.0f sharp sharp sharp blurry sharp
------------------------------------------------------------------------
- Read our Wiki guides for more details!
https://github.com/ocornut/imgui/wiki/Draw-List
- And interactive 1.92.9 vs 1.93.0 comparing testbed:
https://www.dearimgui.com/docs/drawlist_v193
- AddPolyline(), PathStroke(), AddTriangle(): the algorithm to render lines got overhauled.
(#9504, #2183, #2964, #7972 + #9360, #6331, #4250, #4091) [@memononen]
- Generally fixed rendering of thick strokes/paths.
- The new stroke expansion now uses corner miter calculation, which keeps thickness along
the line segments consistent. If the corner becomes too sharp, it will be bevelled to
avoid long spikes at corners.
- There are also some robustness measures for the case where the line thickness is larger
than the features being drawn.
- Rendering artifacts are still possible when the path features are smaller than line thickness,
but the artifacts should be more localized. The new implementation attempted to favor simple
implementation and robustness over the corner case accuracy.
- All functions: new rendering code fixes some inconsistencies between graphics APIs
(e.g. DirectX vs OpenGL) which are using different diamond exits rules. New code should
work precisely the same regardless of graphics API. (#3116, #3258, #2441) [@memononen]
- Debug: added `io.ConfigDebugDrawListDefaultsToStrokeLegacy` to facilitate comparing old/new
behaviors. This is equivalent to calling `PushDrawFlag(ImDrawFlags_StrokeLegacy, true)`
on every drawlist.
Suggested uses, e.g.
- `io.ConfigDebugDrawListDefaultsToStrokeLegacy = io.KeyShift; // Map on holding Shift`
- `ImGui::Checkbox("DefaultsToStrokeLegacy", &io.ConfigDebugDrawListDefaultsToStrokeLegacy);`
- Added `ImDrawFlags_AALineEnds` flag to enable anti-aliased line ends.
- Most noticeable for thick lines.
- Also helps fill minor gaps if combining multiple individual lines. For best looking
continuous lines you should use AddPolyline(), it creates joins between line segments
to avoid any gaps.
- Added `style.AntiAliasedLineEnds` in ImGui to set default state.
- This is disabled by default! Enabling AA Ends by default would be more "correct",
but since it is very slightly slower and increases vertex/index data we decided
to not enable it by default.
This keeps situations such as "throw tens of thousands of lines at ImDrawList"
optimal. You can opt-in for a given shape or in a scope using `PushDrawFlag()`.
- Added `ImDrawFlags_JoinMiter` flag to disable using beveled corner.
- Closer to legacy rendering and slightly faster, but corners sharper than
90 degrees may expand far out.
- Automatically used by AddRect(), AddCircle(), AddNgon(), AddEllipse() functions
since we know that the input path does not contain sharper corners.
- Added `ImDrawFlags_CapSquare` flag to extend lines ends using square caps. (#9360)
- AddConvexPolyFilled()/PathFillConvex(): improved to handle input geometry more robustly.
The rendering of sharp corners was improved. Earlier there were issues with sharp corners
either creating long spikes, or messing up the adjacent edge's anti-aliasing. Now the
anti-aliasing fringe calculation is more consistent, and sharp corners get bevelled to
avoid spikes. There might still be issues when the smallest extent of a long thin polygon
is less than a pixel. Also supports `ImDrawFlags_JoinMiter`, to facilitate matching
a stroke using the same flag.
- AddRect(), AddRectFilled(): various optimizations for rounded rectangles. (#1962, #9504)
- Integer-aligned coordinates and thicknesses will automatically use baked textures,
saving on both CPU and vertex/index data.
- Enabled by default. Use `ImFontAtlasFlags_NoBakedRoundCorners` to disable baking
round corners in font atlas.
- Added `ImDrawFlags_UseTexForRoundCorners` flag to enable in scope or per-shape.
Added for consistency and debugging, not really needed in practice.
- AddCircle, AddCircleFilled: fixed large circles being under-tessellated
(when above ~140 with default CircleTessellationMaxError).
- Improved debug-build performance in various locations.
- Improved minor mismatches when overlapping strokes and filled shapes.
For example, when using inside strokes,
- `AddRect()` and `AddRectFilled()` with rounding now overlap better. (#3656)
- `AddCircle()` and `AddCircleFilled()` now overlap better.
- Added ImDrawList::PushDrawFlag()/PopDrawFlag() to alter certain flags for a
scope and a given `ImDrawList`. (#9489)
- e.g. `PushDrawFlag(ImDrawFlags_StrokeLegacy, true);` enforce legacy tweaks.
- About `ImDrawFlags_StrokeLegacy`:
- This is designed to emulate old behavior:
- Most shapes use `ImDrawFlags_StrokeCenter`.
- AddLine() add +0.5f,+0.5f offset to position.
- AddRect() and AddRectFilled() allow inverted positions.
- AddRectFilled() has no AA when passed non-integer coordinates.
- AddCircle(), AddNgon() add a -0.5f offset to radius.
- Closed shapes use miter corners.
- Lines don't have anti-aliased ends.
- But there are known difference between legacy code and ImDrawFlags_StrokeLegacy:
- Thick shapes with acute angles will now preserve thickness better,
which may make them appear as protruding a little more.
- About disabling anti-aliasing:
- Disabling anti-aliasing is now emulated by applying different UV coordinates.
- It does not result in a performance increase or vertex/index data decrease any more.
(however the tendency is that the new code behaves better than old code).
- But may be a useful stylistic choice in some circumstances.
- Many thick shapes had broken corners with old no-AA code, and the old no-AA code
was wildly different from the AA code. Not the case any more. (#288)
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
- AA Fringe is scaled accordingly.
- Circle and Curves tessellation error are scaled accordingly.
- Reworked assert in PushTexture() to allow convenience grace period of using a
texture that was queue for destroy during the frame. Make it safe to stick to
an existing texture during the frame. (#9528, #8465)
- Added optional `platform_io.DrawCallback_SetSamplerFromTex` standard backend-agnostic
draw callback for requesting to use the sampler associated already associated to a texture.
Currently only supported by the OpenGL2/3 and SDLRenderer3 backend. (#9378)
- Fixed dangling ImDrawList::_OwnerName when using animated label. (#9552) [@ubi-dcastonguay]
- Drags, Sliders:
- Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
@ -136,22 +385,25 @@ Other Changes:
the hashed data. (#9557, #9560) [@sthalik]
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing
issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
- DrawList:
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
- AA Fringe is scaled accordingly.
- Circle and Curves tessellation error are scaled accordingly.
- Reworked assert in PushTexture() to allow convenience grace period of using a
texture that was queue for destroy during the frame. Make it safe to stick to
an existing texture during the frame. (#9528, #8465)
- Added optional `platform_io.DrawCallback_SetSamplerFromTex` standard backend-agnostic
draw callback for requesting to use the sampler associated already associated to a texture.
Currently only supported by the OpenGL2/3 and SDLRenderer3 backend. (#9378)
- Fixed dangling ImDrawList::_OwnerName when using animated label. (#9552) [@ubi-dcastonguay]
- Widgets:
- Checkbox, Menus: check marks use anti-aliased ends.
- Tweaked rendering in various locations to avoid blurryness:
- Windows: title-bar and menu-bar border (when thickness>1.0f).
- SeparatorText: border (when thickness>1.0f).
- Tree: hierarchy lines (when thickness>1.0f).
- InputText: input caret (when thickness>1.0f).
- TabBar: selected overline border (when thickness>1.0f).
- Demo:
- Added `Widgets->Mixed Values` section. (#5518, #5677, #6865)
- Custom Rendering section: exposed new flags; showcasing overlapping strokes
and filled shapes; added an option to animate thickness; added new shapes
to showcase new rendering features that previously hit limitations.
- Style Editor: fixed style/colors combo box applying style when opening Combo.
- Backends:
- QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry]
- Metal, Metal4: added support for rendering inside a render pass with multiple color
attachments (e.g. when merged with other passes): we render to the first color attachment
and leave the other ones untouched. (#9574) [@tqjxlm]
- OpenGL2, OpenGL3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw
callback to request using the sampler associated already associated to a texture. (#9378)
- OpenGL2, OpenGL3: fixed `DrawCallback_ResetRenderState` handler not reseting all states
@ -171,6 +423,9 @@ Other Changes:
Note: this callback is only supported by selected rendering backends: most other graphics API
don't have the equivalent of `SDL_SetTextureScaleMode()` and the callback won't work with them.
- Vulkan: added for support for multiple Vulkan contexts with custom loaders. (#6616) [@lstalmir]
- Vulkan: added support for rendering inside a render pass with multiple color attachments
(e.g. when merged with other passes): we render to the first color attachment and leave the
other ones untouched. (#9574) [@tqjxlm]
- WebGPU: fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport()`
when `FramebufferScale` is >1.0f. (#9515, #8628) [@WayU]
- WebGPU: update to build with wgpu-native 29.0+. (#9377, #9532, #9530) [@lucascompython, @ivan-enzhaev]

View File

@ -403,6 +403,47 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
- likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
2026/10/07 (1.93.0) - large cleanup/refactor of ImDrawList. many issues and inconsistencies fixed! (#9504)
BELOW IS A SIMPLIFIED/SHORTENED RECAP OF CHANGES. READ CHANGELOG AND LINKS ABOVE FOR MORE DETAILS!
useful links:
- ImDrawList 1.92.9 <> 1.93 Interactive Testbed: https://www.dearimgui.com/docs/drawlist_v193 (<-- you can download this locally)
- ImDrawList Wiki Reference: https://github.com/ocornut/imgui/wiki/Draw-List
- Discussion thread: https://github.com/ocornut/imgui/issues/9504
- use ImDrawFlags_StrokeLegacy mode to emulate old rendering:
- Per-primitive: draw_list->AddLine(..., ..., ImDrawFlags_StrokeLegacy);
- For a given scope: draw_list->PushDrawFlag(ImDrawFlags_StrokeLegacy, true); draw_list->AddLine(...); draw_list->PopDrawFlag();
- Globally: ImGui::Checkbox("DefaultsToStrokeLegacy", &io.ConfigDebugDrawListDefaultsToStrokeLegacy); // Map to a checkbox
- Globally: io.ConfigDebugDrawListDefaultsToStrokeLegacy = io.KeyShift; // Map on Shift
- AddLine: removed the (+0.5f,+0.5f) offset that was sneakily added to input coordinates by this function, and led to lots of inconsistencies.
- This fixes inconsistencies in the API and matches the PathXXX API.
- By default, stroke thickness extends on both side of the given segment. e.g for a "pixel-perfect" looking line with thickness=1.0f, coords should be passed as center of each ends of the line.
- Use `ImDrawFlags_StrokeLegacy` to use old offset if required. Or you can apply the offset manually!
- Generally better, simpler and faster to use `AddLineH()`, `AddLineV()` functions added in 1.92.8.
- IF YOU ARE MINDFUL OF PIXEL-PERFECTNESS IN YOUR CUSTOM RENDERING/WIDGETS read Changelog and links above for details.
- AddRect(), AddCircle(), AddNgon(), AddEllipse(), AddTriangle(), AddQuad(): defaulting to "inside" stroke. All closed shapes with thickness=1.0f will appear identical. The difference for thickness>1.0f shapes may be minimal since very large strokes were not well supported for widgets, but stroke will default inside widgets.
- AddCircle(), AddNgon(): removed +0.5f offset added to radius. This fixes inconsistencies in the API. Use `ImDrawFlags_StrokeLegacy` to use old method if required. Or you can apply the offset manually!
- AddRectFilled(): non-integer coordinates will now display anti-aliased edges. Previously, non-integer coordinates rendered with aliased edges snapped by the rasterizer.
- AddRect(), AddRectFilled(): rectangles with inverted coordinates won't be visible unless using ImDrawList_StrokeLegacy mode.
With inverted coordinates:
- Legacy `AddRect()` rounding off -> visible but incorrect outer size.
- Legacy `AddRect()` rounding on -> visible but very glitchy.
- Legacy `AddRectFilled()` rounding off -> visible and correct.
- Legacy `AddRectFilled()` rounding on -> visible but very glitchy.
- merged ImDrawListFlags into ImDrawFlags. obsoleted ImDrawListFlags (which were rarely used directly):
- ImDrawListFlags_AntiAliasedLines -> ImDrawFlags_AALines,
- ImDrawListFlags_AntiAliasedFill -> ImDrawFlags_AAFill,
- ImDrawListFlags_AllowVtxOffset -> ImDrawFlags_UseVtxOffset,
- ImDrawListFlags_TextNoPixelSnap -> ImDrawFlags_TextNoPixelSnap,
unifying them allows easily using them for both per-primitives alterations and scope alterations.
- renamed ImDrawFlags_RoundCornersXXXX to ImDrawFlags_RoundXXXX.
- ImDrawFlags_RoundCornersAll -> ImDrawFlags_RoundAll,
- ImDrawFlags_RoundCornersNone -> ImDrawFlags_RoundNone,
- ImDrawFlags_RoundCornersTopLeft -> ImDrawFlags_RoundTopLeft,
- ImDrawFlags_RoundCornersTopRight -> ImDrawFlags_RoundTopRight,
- ImDrawFlags_RoundCornersTop -> ImDrawFlags_RoundTop,
- ImDrawFlags_RoundCornersBottom -> ImDrawFlags_RoundBottom,
etc. kept redirection enums (will obsolete).
- obsoleted style.AntiAliasedLinesUseTex and ImDrawListFlags_AntiAliasedLinesUseTex, as the new line rendering code always uses textures.
- 2026/09/30 (1.93.0) - ImFont: renamed `AddRemapChar()` to `AddRemapCodepoint()` (rarely used, marked internal). (#609, #5748)
- 2026/09/18 (1.93.0) - ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`: prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit.
@ -1606,9 +1647,9 @@ ImGuiStyle::ImGuiStyle()
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
// Rendering & Tessellation
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Used at the beginning of the frame to set ImDrawFlags_AALines in all draw-lists.
AntiAliasedLineEnds = false; // Enable anti-aliased lines/borders ends. Nicer for thick lines but more expensive. Used at the beginning of the frame to set ImDrawFlags_AALineEnds in all draw-lists.
AntiAliasedFill = true; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Used at the beginning of the frame to set ImDrawFlags_AAFill in all draw-lists.
CurveTessellationMaxError = 1.12f; // Maximum error (in pixels) when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
@ -1624,6 +1665,7 @@ ImGuiStyle::ImGuiStyle()
_NextFrameFontSizeBase = 0.0f;
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
CurveTessellationTol = 0.0f; // Old CurveTessellationTol = CurveTessellationMaxError*CurveTessellationMaxError.
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures for legacy strokes. Require backend to render with bilinear filtering (NOT point/nearest filtering).
#endif
// Default theme
@ -5805,15 +5847,21 @@ static void SetupDrawListSharedData()
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
g.DrawListSharedData.CurveTessellationMaxError = g.Style.CurveTessellationMaxError;
g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
if (g.Style.AntiAliasedLines)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
if (g.Style.AntiAliasedLinesUseTex && !(g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines))
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
g.DrawListSharedData.InitialDrawFlags = ImDrawFlags_None;
if (g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines)
g.Style.AntiAliasedLines = g.Style.AntiAliasedLineEnds = false;
if (g.Style.AntiAliasedFill)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_AAFill;
if (g.Style.AntiAliasedLines)
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_AALines;
if (g.Style.AntiAliasedLineEnds)
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_AALineEnds;
if (g.IO.ConfigDebugDrawListDefaultsToStrokeLegacy)
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_StrokeLegacy;
if (!(g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedRoundCorners))
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_UseTexForRoundCorners | ImDrawFlags_AllowTexForRoundCorners_;
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_UseVtxOffset;
}
void ImGui::NewFrame()
@ -7623,7 +7671,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
float y = window->Pos.y + window->TitleBarHeight - 1;
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);
window->DrawList->AddLineH(window->Pos.x + border_size, window->Pos.x + window->Size.x - border_size, y, border_col, g.Style.FrameBorderSize, ImDrawFlags_StrokeCenterBiased);
}
}
@ -7703,7 +7751,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (window->DockIsActive)
bg_rounding_flags = CalcRoundingFlagsForRectInRect(bg_rect, window->DockNode->HostWindow->Rect(), 0.0f);
else
bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersBottom;
bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundAll : ImDrawFlags_RoundBottom;
ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
if (window->DockIsActive)
bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
@ -7723,7 +7771,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
if (window->ViewportOwned)
title_bar_col |= IM_COL32_A_MASK; // No alpha
window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundTop);
}
// Menu bar
@ -7731,9 +7779,9 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
{
ImRect menu_bar_rect = window->MenuBarRect();
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);
window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundTop);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
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);
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size, menu_bar_rect.Max.x - window_border_size, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize, ImDrawFlags_StrokeCenterBiased);
}
// Docking: Unhide tab bar (small triangle in the corner), drag from small triangle to quickly undock
@ -23615,10 +23663,9 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
Selectable(buf, false);
if (fg_draw_list && IsItemHovered())
{
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->PushDrawFlag(ImDrawFlags_AALines, false); // 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), 1.0f, ImDrawFlags_Closed);
fg_draw_list->Flags = backup_flags;
fg_draw_list->PopDrawFlag();
}
}
TreePop();
@ -23634,8 +23681,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
// Draw wire-frame version of all triangles
ImRect clip_rect = draw_cmd->ClipRect;
ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
ImDrawListFlags backup_flags = out_draw_list->Flags;
out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
out_draw_list->PushDrawFlag(ImDrawFlags_AALines, false); // Disable AA on triangle outlines is more readable for very large and thin triangles.
for (unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; )
{
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; // We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list
@ -23653,7 +23699,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU
out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles
}
out_draw_list->Flags = backup_flags;
out_draw_list->PopDrawFlag();
}
// [DEBUG] Compute mask of inputs with the same codepoint.
@ -24303,9 +24349,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->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);
window->DrawList->AddLineH(curr_x - 4.0f, curr_x + 5.0f, line_y1, col, 1.0f);
window->DrawList->AddLineV(curr_x, line_y1, line_y2, col, 1.0f);
window->DrawList->AddLineH(curr_x - 4.0f, curr_x + 5.0f, line_y2, col, 1.0f);
}
// Draw last item rect in ForegroundDrawList (so it is always visible)

221
imgui.h
View File

@ -30,7 +30,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.93.0 WIP"
#define IMGUI_VERSION_NUM 19297
#define IMGUI_VERSION_NUM 19298
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
@ -51,7 +51,7 @@ Index of this file:
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiWindowClass, ImGuiPayload)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiMultiSelectIO, ImGuiSelectionRequest, ImGuiSelectionBasicStorage, ImGuiSelectionExternalStorage)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawList, ImDrawData)
// [SECTION] Texture API (ImTextureFormat, ImTextureStatus, ImTextureRect, ImTextureData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFontBaked, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
@ -250,7 +250,6 @@ typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A
// - In Visual Studio w/ Visual Assist installed: Alt+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: Ctrl+Click can follow symbols inside comments.
typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
typedef int ImDrawTextFlags; // -> enum ImDrawTextFlags_ // Internal, do not use!
typedef int ImFontFlags; // -> enum ImFontFlags_ // Flags: for ImFont
typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas
@ -2484,9 +2483,9 @@ struct ImGuiStyle
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later.
// Rendering & Tessellation
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Used at the beginning of the frame to set ImDrawFlags_AALines in all draw-lists.
bool AntiAliasedLineEnds; // Enable anti-aliased lines/borders ends. Nicer for thick lines but more expensive. Used at the beginning of the frame to set ImDrawFlags_AALineEnds in all draw-lists.
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Used at the beginning of the frame to set ImDrawFlags_AAFill in all draw-lists.
float CurveTessellationMaxError; // Maximum error (in pixels) when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
@ -2511,6 +2510,7 @@ struct ImGuiStyle
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
bool AntiAliasedLinesUseTex; // [OBSOLETE] Enable anti-aliased lines/borders using textures for legacy strokes. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
float CurveTessellationTol; // [OBSOLETE] Old CurveTessellationTol = New CurveTessellationMaxError*CurveTessellationMaxError. // Changed in 1.93.0
// TabMinWidthForCloseButton = TabCloseButtonMinWidthUnselected // Renamed in 1.91.9.
#endif
@ -2667,6 +2667,11 @@ struct ImGuiIO
// - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys()/io.ClearInputMouse() in input processing.
// Option to compare < 1.93.0 rendering details vs 1.93.0 rendering details. (#9504)
// - Equivalent to calling PushDrawFlag(ImDrawList_StrokeLegacy,true) on every draw list instances.
// - Suggested use, e.g. io.ConfigDebugDrawListDefaultsToStrokeLegacy = io.KeyShift; // Map to SHIFT modifier
bool ConfigDebugDrawListDefaultsToStrokeLegacy; // false // Default all ImDrawList to ImDrawList_StrokeLegacy mode, mimicking pre-1.93.0 rendering.
//------------------------------------------------------------------
// Platform Identifiers
// (the imgui_impl_xxxx backend files are setting those up for you)
@ -3019,6 +3024,20 @@ struct ImGuiStorage
#endif
};
// [Internal] Used for small stacks. Do not use.
template<typename T, int Capacity, typename SZ_T = ImU16>
struct ImSmallStack_
{
T LocalData[Capacity]; // FIXME: should evolve into using heap, e.g union {} with T* HeapData + add SZ_T Capacity.
SZ_T Size = 0;
inline void clear() { Size = 0; }
inline T& back() { IM_ASSERT(Size > 0); return LocalData[Size - 1]; }
inline void push_back(const T& v) { IM_ASSERT(Size < Capacity); memcpy(&LocalData[Size], &v, sizeof(v)); Size++; }
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
inline int capacity() const { return Capacity; }
};
// Flags for ImGuiListClipper (currently not fully exposed in function calls: a future refactor will likely add this to ImGuiListClipper::Begin function equivalent)
enum ImGuiListClipperFlags_
{
@ -3332,15 +3351,10 @@ struct ImGuiSelectionExternalStorage
};
//-----------------------------------------------------------------------------
// [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawList, ImDrawData)
// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.
//-----------------------------------------------------------------------------
// The maximum line width to bake anti-aliased textures for. Build atlas with ImFontAtlasFlags_NoBakedLines to disable baking.
#ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX
#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (32)
#endif
// ImDrawIdx: vertex index. [Compile-time configurable type]
// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended).
// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file.
@ -3434,40 +3448,82 @@ struct ImDrawListSplitter
// Flags for ImDrawList functions
enum ImDrawFlags_
{
ImDrawFlags_None = 0,
ImDrawFlags_None = 0,
//ImDrawFlags_Closed = 1, // -> FLAG MOVED BELOW. Prior to 1.92.8 (May 2026): ImDrawFlags_Closed was guaranteed to be == (1<<0) == 1, for legacy compatibility reason. Hardcoded use of 1 or true should be replaced with 'ImDrawFlags_Closed'.
// Rounding for AddRect(), AddRectFilled(), PathRect()
// - When not specified, we defaults to ImDrawFlags_RoundCornersAll! So you only need to use those flags if you want another configuration.
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // Round top-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersTopRight = 1 << 5, // Round top-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // Round bottom-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // Round bottom-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersNone = 1 << 8, // Disable rounding even if `float rounding > 0.0f`. This is NOT zero, NOT an implicit flag!
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, // (Default!!)
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified!
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
// About usage of flags:
// - "Prim" column: 'OK' = flag can be used to configure an individual AddXXX() call.
// - "Scope" column: 'OK' = initialized by ImGui based on Style options (e.g. whether anti-aliased is enabled) + may be modified using ImDrawList::PushDrawFlag().
// OK(0)/OK(1) indicates whether this flag is set in the default ImGui Style settings.
// Stroke options
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed.
//ImDrawFlags_Closed = 1, // Prior to 1.92.8 (May 2026), ImDrawFlags_Closed was guaranteed to be == 1<<0 == 1 for legacy compatibility reason. Hardcoded use of 1 or true should be replaced.
// - Rounding default to ImDrawFlags_RoundAll when 'rounding > 0'.
// - So you only need to use the ImDrawFlags_RoundXXX flags if you want a special configuration (e.g. a rectangle with one rounded corner).
// Rounding for AddRectXXX(), PathRect() ------ // Prim/Scope?
ImDrawFlags_RoundTopLeft = 1 << 4, // OK -- // Round top-left corner only (when 'rounding > 0.0f', we default to all corners).
ImDrawFlags_RoundTopRight = 1 << 5, // OK -- // Round top-right corner only (when 'rounding > 0.0f', we default to all corners).
ImDrawFlags_RoundBottomLeft = 1 << 6, // OK -- // Round bottom-left corner only (when 'rounding > 0.0f', we default to all corners).
ImDrawFlags_RoundBottomRight = 1 << 7, // OK -- // Round bottom-right corner only (when 'rounding > 0.0f', we default to all corners).
ImDrawFlags_RoundNone = 1 << 8, // OK -- // Disable rounding even when 'rounding > 0.0f'. This value is NOT zero, it is NOT an implicit flag!
ImDrawFlags_RoundAll = ImDrawFlags_RoundTopLeft | ImDrawFlags_RoundTopRight | ImDrawFlags_RoundBottomLeft | ImDrawFlags_RoundBottomRight, // (Default!!)
ImDrawFlags_RoundTop = ImDrawFlags_RoundTopLeft | ImDrawFlags_RoundTopRight,
ImDrawFlags_RoundBottom = ImDrawFlags_RoundBottomLeft | ImDrawFlags_RoundBottomRight,
ImDrawFlags_RoundLeft = ImDrawFlags_RoundBottomLeft | ImDrawFlags_RoundTopLeft,
ImDrawFlags_RoundRight = ImDrawFlags_RoundBottomRight | ImDrawFlags_RoundTopRight,
ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // == 0x8000000F,
};
// Stroke Options ----------------------------- // Prim/Scope?
ImDrawFlags_Closed = 1 << 9, // OK -- // PathStroke(), AddPolyline(): specify that shape should be closed.
ImDrawFlags_JoinMiter = 1 << 10, // OK -- // PathStroke(), AddPolyline(): use miter joins/corners only. This assumes that the input polyline does not have corners sharper than 90 degrees. Slightly faster.
ImDrawFlags_CapSquare = 1 << 11, // OK -- // PathStroke(), AddPolyline(): use square cap line ends.
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
// It is however possible to temporarily alter flags between calls to ImDrawList:: functions.
enum ImDrawListFlags_
{
ImDrawListFlags_None = 0,
ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles)
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
ImDrawListFlags_TextNoPixelSnap = 1 << 4, // Disable automatically snapping AddText() calls to pixel boundaries.
// About Stroke Ends:
// - Rendering is optimized for fast pixel-perfect UI, so line ends are not anti-aliased by default. It's cheaper (we can emit less vertices).
// - For more free-form drawings, light graphs and markers, or when using thick strokes: you can turn them on using the ImDrawFlags_AALineEnds flag.
// - See 'Demo->Examples->Custom Rendering' to interactively toy with those flags.
// - 'OK*' indicates using this at the AddXXX() call site is unlikely: it would only makes sense if (1) the option is disabled in style/scope and (2) you want to forcefully enable it for a single primitives. Possible but unlikely! Only supported for functions taking flags inputs.
// Stroke/Fill Anti-aliasing ------------------ // Prim/Scope?
ImDrawFlags_AAFill = 1 << 12, // OK* OK(1) // Enable anti-aliasing for Filled shapes.
ImDrawFlags_AALines = 1 << 13, // OK* OK(1) // Enable anti-aliasing for Strokes (lines, borders).
ImDrawFlags_AALineEnds = 1 << 14, // OK OK(0) // Enable anti-aliasing for Strokes Ends. Requires AALines to also be enabled. Useful on thick strokes or for precise continuity of multiple lines. A little more costly.
//ImDrawFlags_NoAA = 1 << 15, // OK -- // Disable anti-aliasing for a given primitive.
//ImDrawFlags_NoAALineEnds = 1 << 16, // OK -- // Disable anti-aliasing ends for a given primitive.
// About Stroke Position:
// - Read https://github.com/ocornut/imgui/wiki/Draw-List (this guide includes a precise list of differences between 1.92.9 and 1.93.0)
// - Read https://github.com/ocornut/imgui/wiki/Pixel-Perfect-Rendering
// Stroke Position relative to shape outline -- // Prim/Scope?
ImDrawFlags_StrokeInside = 1 << 17, // OK -- // Draw stroke inside of the shape outline (default for closed shapes and AddLineH, AddLineV functions)
ImDrawFlags_StrokeCenter = 2 << 17, // OK -- // Draw stroke at the center of the shape outline (default for paths, bezier, and AddLine functions)
ImDrawFlags_StrokeCenterBiased = 3 << 17, // OK -- // Draw stroke at the center of the shape outline, so that half thickness rounded down will be outside, and the rest inside the shape outline. Useful for axis-aligned shapes: AddLineH, AddLineV, AddRect. Does not animate well!
ImDrawFlags_StrokeOutside = 4 << 17, // OK -- // Draw stroke outside of the shape outline
ImDrawFlags_StrokeLegacy = 7 << 17, // OK OK(0) // Use legacy positioning + enable JoinMiter + disable AALineEnds. Must be all bits set.
// Other Options ------------------------------ // Prim/Scope?
ImDrawFlags_TextNoPixelSnap = 1 << 20, // OK OK(0) // Disable automatically snapping AddText() calls to pixel boundaries.
ImDrawFlags_UseTexForRoundCorners = 1 << 21, // -- OK(1) // Enable using textures instead of strokes to draw rounded corners/circles where possible (faster). Used by default unless 'ImFontAtlasFlags_NoBakedRoundCorners' is enabled in the font atlas.
ImDrawFlags_UseVtxOffset = 1 << 22, // -- OK(1) // Can emit 'VtxOffset > 0' to allow large meshes with 16-bit ImDrawIdx. Used by default when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled by the backend.
ImDrawFlags_AllowTexForRoundCorners_= 1 << 23, // -- OK(1) // [Internal]
// [Internal]
ImDrawFlags_RoundMask_ = ImDrawFlags_RoundAll | ImDrawFlags_RoundNone, // [Internal]
ImDrawFlags_AllowInPushScope_ = ImDrawFlags_AAFill | ImDrawFlags_AALines | ImDrawFlags_AALineEnds | ImDrawFlags_StrokeLegacy | ImDrawFlags_TextNoPixelSnap | ImDrawFlags_UseTexForRoundCorners | ImDrawFlags_UseVtxOffset | ImDrawFlags_RoundMask_, // [Internal] Values allowed in PushDrawFlag() scope.
ImDrawFlags_AllowInFrameScope_ = ImDrawFlags_AllowInPushScope_ | ImDrawFlags_AllowTexForRoundCorners_,
ImDrawFlags_StrokeMask_ = 0x07 << 17, // [Internal]
ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // [Internal] == 0x8000000F. Reserved to detect misuses.
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// RENAMED in 1.93.0 (Oct 2026): ImDrawFlags_RoundCornersXXXX -> ImDrawFlags_RoundXXXX.
ImDrawFlags_RoundCornersTopLeft = ImDrawFlags_RoundTopLeft,
ImDrawFlags_RoundCornersTopRight = ImDrawFlags_RoundTopRight,
ImDrawFlags_RoundCornersBottomLeft = ImDrawFlags_RoundBottomLeft,
ImDrawFlags_RoundCornersBottomRight = ImDrawFlags_RoundBottomRight,
ImDrawFlags_RoundCornersNone = ImDrawFlags_RoundNone,
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundAll,
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundTop,
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundBottom,
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundLeft,
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundRight,
#endif
};
// Draw command list
@ -3485,7 +3541,7 @@ struct ImDrawList
ImVector<ImDrawCmd> CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback.
ImVector<ImDrawIdx> IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those
ImVector<ImDrawVert> VtxBuffer; // Vertex buffer.
ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
ImDrawFlags Flags; // Current flags for drawing primitives. Alter with PushDrawFlag()/PopDrawFlags() to adjust defaults to a given scope.
// [Internal, used while building lists]
unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0.
@ -3498,8 +3554,10 @@ struct ImDrawList
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureRef> _TextureStack; // [Internal]
ImVector<ImU8> _CallbacksDataBuf; // [Internal]
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content.
ImSmallStack_<ImDrawFlags,3> _DrawFlagsStack;// [Internal]
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
float _InvFringeScale; // [internal] 1.0 / _FringeScale // FIXME: Consider renaming to _PixelDensity.
bool _FringeScaleIsInteger; // [Internal] true if 1/_FringeScale is a whole number, used to select fast path for rendering
const char* _OwnerName; // Pointer to owner window's name for debugging
// If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData().
@ -3512,6 +3570,8 @@ struct ImDrawList
IMGUI_API void PopClipRect();
IMGUI_API void PushTexture(ImTextureRef tex_ref);
IMGUI_API void PopTexture();
IMGUI_API void PushDrawFlag(ImDrawFlags flags, bool enabled); // [BETA] Please notify me if you are using this.
IMGUI_API void PopDrawFlag();
inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }
inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }
@ -3522,32 +3582,32 @@ struct ImDrawList
// In older versions (until Dear ImGui 1.77) the AddCircle functions defaulted to num_segments == 12.
// 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 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 AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
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);
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col);
IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col);
IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f);
IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0);
IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f);
IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments);
IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f);
IMGUI_API void AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f, ImDrawFlags flags = 0);
IMGUI_API void AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0);
IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points)
IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Cubic Bezier (4 control points)
IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0, ImDrawFlags flags = 0); // Quadratic Bezier (3 control points)
// 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, float thickness, ImDrawFlags flags = 0);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
inline void AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0) { _AddPolyline(points, num_points, col, thickness, flags, FLT_MAX); }
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags = 0);
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
// Image primitives
@ -3564,9 +3624,9 @@ struct ImDrawList
inline void PathClear() { _Path.Size = 0; }
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
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 PathFillConvex(ImU32 col, ImDrawFlags flags = 0) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, flags); _Path.Size = 0; }
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _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; }
inline void PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0) { _AddPolyline(_Path.Data, _Path.Size, col, thickness, flags, FLT_MAX); _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
@ -3644,6 +3704,13 @@ struct ImDrawList
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
IMGUI_API void _AddRectFilledBaked(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float r, const ImVec4& tex_uvs, ImDrawFlags flags);
IMGUI_API void _AddRectBaked(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float r, float t, const ImVec4& tex_uvs, ImDrawFlags flags);
IMGUI_API void _AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness, ImDrawFlags flags);
IMGUI_API void _AddRectTinyRounding(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags);
IMGUI_API void _SelectLineTexture(float screen_thickness, ImVec2* out_uv0, ImVec2* out_uv1, float* out_fringe, ImDrawFlags flags);
IMGUI_API float _CalculateCenterBiasedOffset(float thickness);
IMGUI_API void _AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags, float max_inner_offset);
};
// All draw data to render a Dear ImGui frame
@ -3860,7 +3927,8 @@ enum ImFontAtlasFlags_
ImFontAtlasFlags_None = 0,
ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two
ImFontAtlasFlags_NoMouseCursors = 1 << 1, // Don't build software mouse cursors into the atlas (save a little texture memory)
ImFontAtlasFlags_NoBakedLines = 1 << 2, // Don't build thick line textures into the atlas (save a little texture memory, allow support for point/nearest filtering). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU).
ImFontAtlasFlags_NoBakedLines = 1 << 2, // Don't build anti-aliased line textures into the atlas (save a little texture memory). SINCE 1.93.0 THIS PREVENTS ANTI-ALIASED LINES FROM WORKING AND WILL DISABLE THEM.
ImFontAtlasFlags_NoBakedRoundCorners= 1 << 3, // Don't build round corners into the atlas.
};
// Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding:
@ -3977,7 +4045,7 @@ struct ImFontAtlas
// Input
ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
ImTextureFormat TexDesiredFormat; // Desired texture format (default to ImTextureFormat_RGBA32 but may be changed to ImTextureFormat_Alpha8).
int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false).
int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method never relies on bilinear filtering you may set this to 0.
int TexMinWidth; // Minimum desired texture width. Must be a power of two. Default to 512.
int TexMinHeight; // Minimum desired texture height. Must be a power of two. Default to 128.
int TexMaxWidth; // Maximum desired texture width. Must be a power of two. Default to 8192.
@ -4004,7 +4072,6 @@ struct ImFontAtlas
ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel. May change as new texture gets created.
ImVector<ImFont*> Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.
ImVector<ImFontConfig> Sources; // Source/configuration data
ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines
int TexNextUniqueID; // Next value to be stored in TexData->UniqueID
int FontNextUniqueID; // Next value to be stored in ImFont->FontID
ImVector<ImDrawListSharedData*> DrawListSharedDatas; // List of users for this atlas. Typically one per Dear ImGui context.
@ -4523,6 +4590,18 @@ namespace ImGui
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8) // OBSOLETED in 1.92.8: Use ImGui::GetPlatformIO().DrawCallback_ResetRenderState
// -- RENAMED in 1.93.0: Merged ImDrawListFlags into ImDrawFlags.
typedef ImDrawFlags ImDrawListFlags;
enum ImDrawListFlags_
{
ImDrawListFlags_None = ImDrawFlags_None,
ImDrawListFlags_AntiAliasedFill = ImDrawFlags_AAFill,
ImDrawListFlags_AntiAliasedLines = ImDrawFlags_AALines,
ImDrawListFlags_AntiAliasedLinesUseTex = ImDrawFlags_AALines, // No effect, anti-aliased rendering always uses textures from 1.93+
ImDrawListFlags_AllowVtxOffset = ImDrawFlags_UseVtxOffset,
ImDrawListFlags_TextNoPixelSnap = ImDrawFlags_TextNoPixelSnap,
};
//-- OBSOLETED in 1.92.0: ImFontAtlasCustomRect becomes ImTextureRect
// - ImFontAtlasCustomRect::X,Y --> ImTextureRect::x,y
// - ImFontAtlasCustomRect::Width,Height --> ImTextureRect::w,h
@ -4546,16 +4625,16 @@ typedef ImFontAtlasRect ImFontAtlasCustomRect;
//typedef ImDrawFlags ImDrawCornerFlags;
//enum ImDrawCornerFlags_
//{
// ImDrawCornerFlags_None = ImDrawFlags_RoundCornersNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundCornersNone which is != 0 and not implicit
// ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundCornersTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally).
// ImDrawCornerFlags_TopRight = ImDrawFlags_RoundCornersTopRight, // Was == 0x02 (1 << 1) prior to 1.82.
// ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundCornersBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82.
// ImDrawCornerFlags_BotRight = ImDrawFlags_RoundCornersBottomRight, // Was == 0x08 (1 << 3) prior to 1.82.
// ImDrawCornerFlags_All = ImDrawFlags_RoundCornersAll, // Was == 0x0F prior to 1.82
// ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight,
// ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight,
// ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft,
// ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight,
// ImDrawCornerFlags_None = ImDrawFlags_RoundNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundNone which is != 0 and not implicit
// ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally).
// ImDrawCornerFlags_TopRight = ImDrawFlags_RoundTopRight, // Was == 0x02 (1 << 1) prior to 1.82.
// ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82.
// ImDrawCornerFlags_BotRight = ImDrawFlags_RoundBottomRight, // Was == 0x08 (1 << 3) prior to 1.82.
// ImDrawCornerFlags_All = ImDrawFlags_RoundAll, // Was == 0x0F prior to 1.82
// ImDrawCornerFlags_Top = ImDrawFlags_RoundTopLeft | ImDrawFlags_RoundTopRight,
// ImDrawCornerFlags_Bot = ImDrawFlags_RoundBottomLeft | ImDrawFlags_RoundBottomRight,
// ImDrawCornerFlags_Left = ImDrawFlags_RoundTopLeft | ImDrawFlags_RoundBottomLeft,
// ImDrawCornerFlags_Right = ImDrawFlags_RoundTopRight | ImDrawFlags_RoundBottomRight,
//};
// RENAMED and MERGED both ImGuiKey_ModXXX and ImGuiModFlags_XXX into ImGuiMod_XXX (from September 2022)

View File

@ -640,6 +640,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
ImGui::SameLine(); HelpMarker("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
ImGui::Checkbox("io.ConfigDebugDrawListDefaultsToStrokeLegacy", &io.ConfigDebugDrawListDefaultsToStrokeLegacy);
ImGui::SameLine(); HelpMarker("Option to default all ImDrawList to ImDrawFlags_StrokeLegacy mode, mimicking pre-1.93.0 rendering.");
ImGui::Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
ImGui::SameLine(); HelpMarker("Option to save .ini data with extra comments (particularly helpful for Docking, but makes saving slower).");
@ -9025,12 +9027,21 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
SameLine();
HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
BeginDisabled(style.AntiAliasedLines == false);
Checkbox("Anti-aliased line ends", &style.AntiAliasedLineEnds);
EndDisabled();
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
BeginDisabled();
Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
SameLine();
HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
EndDisabled();
#endif
Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
Checkbox("Debug: DrawList Defaults to _StrokeLegacy", &ImGui::GetIO().ConfigDebugDrawListDefaultsToStrokeLegacy);
PushItemWidth(GetFontSize() * 8);
DragFloat("Curve Tessellation Max Error", &style.CurveTessellationMaxError, 0.02f, 0.10f, 10.0f, "%.2f");
if (style.CurveTessellationMaxError < 0.10f)
@ -10448,13 +10459,10 @@ static void ShowExampleAppWindowTitles(bool*)
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
//-----------------------------------------------------------------------------
// Add a |_| looking shape
static void PathConcaveShape(ImDrawList* draw_list, float x, float y, float sz)
{
const ImVec2 pos_norms[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } };
for (const ImVec2& p : pos_norms)
draw_list->PathLineTo(ImVec2(x + 0.5f + (int)(sz * p.x), y + 0.5f + (int)(sz * p.y)));
}
// See our Wiki guides:
// - ImDrawList Vector Rendering Reference: https://github.com/ocornut/imgui/wiki/Draw-List
// - Pixel Perfect Anti-aliased Rendering: https://github.com/ocornut/imgui/wiki/Pixel-Perfect-Rendering
// - How Anti-aliased Polyline Rendering is Implemented: https://github.com/ocornut/imgui/wiki/Polyline-Rendering
// Demonstrate using the low-level ImDrawList to draw custom shapes.
static void ShowExampleAppCustomRendering(bool* p_open)
@ -10486,118 +10494,250 @@ static void ShowExampleAppCustomRendering(bool* p_open)
ImGui::Text("Gradients");
ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
{
ImVec2 p0 = ImGui::GetCursorScreenPos();
ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
ImGui::InvisibleButton("##gradient1", gradient_size);
ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
ImGui::InvisibleButton("##gradient1", gradient_size);
draw_list->AddRectFilledMultiColor(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), col_a, col_b, col_b, col_a);
}
{
ImVec2 p0 = ImGui::GetCursorScreenPos();
ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
ImGui::InvisibleButton("##gradient2", gradient_size);
ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
ImGui::InvisibleButton("##gradient2", gradient_size);
draw_list->AddRectFilledMultiColor(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), col_a, col_b, col_b, col_a);
}
// Draw a bunch of primitives
ImGui::Text("All primitives");
static float sz = 42.0f;
static float thickness = 3.0f;
static int ngon_sides = 6;
static float base_rounding = 8.0f;
static float base_thickness = 3.0f;
static bool animate_rounding = false;
static bool animate_thickness = false;
static int ngon_segments = 6;
static bool circle_segments_override = false;
static int circle_segments_override_v = 12;
static bool curve_segments_override = false;
static int curve_segments_override_v = 8;
static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40);
ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40);
ImGui::ColorEdit4("Color", &colf.x);
static ImVec4 colf_stroke = ImVec4(1.000f, 0.384f, 0.169f, 1.000f);
static ImVec4 colf_fill = ImVec4(0.416f, 0.378f, 0.420f, 1.000f);
const ImVec2 p = ImGui::GetCursorScreenPos();
const ImU32 col = ImColor(colf);
const float spacing = 10.0f;
const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
const float rounding = sz / 5.0f;
ImGui::DragFloat("Size", &sz, 0.2f, 0.2f, 100.0f, "%.0f");
const float rounding_anim_period = 3.0f;
const float rounding_wave = 1.0f - fabsf(fmodf((float)ImGui::GetTime(), rounding_anim_period) * (2.0f / rounding_anim_period) - 1.0f);
const float rounding = animate_rounding ? (float)(int)(rounding_wave * base_rounding * 10.0f) / 10.0f : base_rounding; // Sub-integer rounding works but has discontinuities in small values, so best disable we
ImGui::DragFloat("Rounding", &base_rounding, 0.02f, 0.0f, 32.0f, "%.1f"); ImGui::SameLine();
ImGui::Checkbox("Animate##rounding", &animate_rounding); ImGui::SameLine();
ImGui::Text("%.2f", rounding);
const float thickness_anim_period = 5.0f;
const float thickness_wave = 1.0f - fabsf(fmodf((float)ImGui::GetTime(), thickness_anim_period) * (2.0f / thickness_anim_period) - 1.0f);
const float thickness = animate_thickness ? thickness_wave * base_thickness : base_thickness;
ImGui::DragFloat("Thickness", &base_thickness, 0.02f, 0.0f, 32.0f, "%.02f"); ImGui::SameLine();
ImGui::Checkbox("Animate##thickness", &animate_thickness); ImGui::SameLine();
ImGui::Text("%.2f", thickness);
ImGui::SliderInt("N-gon sides", &ngon_segments, 3, 12);
ImGui::Checkbox("##CircleSegmentOverride", &circle_segments_override);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 30);
ImGui::Checkbox("##CurvesSegmentOverride", &curve_segments_override);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 30);
ImGui::ColorEdit4("Stroke Color", &colf_stroke.x);
ImGui::ColorEdit4("Fill Color", &colf_fill.x);
static ImDrawFlags prim_stroke_flags = ImDrawFlags_None;
static ImDrawFlags prim_other_flags = ImDrawFlags_AALineEnds;
ImGui::SeparatorText("Per primitive flags (AddXXX functions)");
ImGui::RadioButton("Default", &prim_stroke_flags, ImDrawFlags_None); ImGui::SameLine();
ImGui::RadioButton("Inside", &prim_stroke_flags, ImDrawFlags_StrokeInside); ImGui::SameLine();
ImGui::RadioButton("Center", &prim_stroke_flags, ImDrawFlags_StrokeCenter); ImGui::SameLine();
ImGui::RadioButton("CenterBiased", &prim_stroke_flags, ImDrawFlags_StrokeCenterBiased); ImGui::SameLine();
ImGui::RadioButton("Outside", &prim_stroke_flags, ImDrawFlags_StrokeOutside); ImGui::SameLine();
ImGui::RadioButton("Legacy", &prim_stroke_flags, ImDrawFlags_StrokeLegacy);
ImGui::CheckboxFlags("AAFill", &prim_other_flags, ImDrawFlags_AAFill); ImGui::SameLine(); // Note: Only for functions taking flags.
ImGui::CheckboxFlags("AALines", &prim_other_flags, ImDrawFlags_AALines); ImGui::SameLine(); // Note: Only for functions taking flags.
ImGui::CheckboxFlags("AALineEnds", &prim_other_flags, ImDrawFlags_AALineEnds); ImGui::SameLine();
ImGui::CheckboxFlags("JoinMiter", &prim_other_flags, ImDrawFlags_JoinMiter); ImGui::SameLine();
ImGui::CheckboxFlags("CapSquare", &prim_other_flags, ImDrawFlags_CapSquare);
//ImGui::CheckboxFlags("UseTexForRoundCorners", &prim_other_flags, ImDrawFlags_UseTexForRoundCorners);
static ImDrawFlags scope_flags = draw_list->Flags & ImDrawFlags_AllowInPushScope_; // First init copy current state.
ImGui::SeparatorText("Current ImDrawList flags (e.g. PushDrawFlag function)");
ImGui::PushID("ScopeFlags");
ImGui::CheckboxFlags("AAFill", &scope_flags, ImDrawFlags_AAFill); ImGui::SameLine();
ImGui::CheckboxFlags("AALines", &scope_flags, ImDrawFlags_AALines); ImGui::SameLine();
ImGui::CheckboxFlags("AALineEnds", &scope_flags, ImDrawFlags_AALineEnds); ImGui::SameLine();
ImGui::CheckboxFlags("StrokeLegacy", &scope_flags, ImDrawFlags_StrokeLegacy);
//ImGui::CheckboxFlags("UseTexForRoundCorners", &scope_flags, ImDrawFlags_UseTexForRoundCorners);
ImGui::PopID();
ImGui::Spacing();
draw_list->PushDrawFlag(ImDrawFlags_AllowInPushScope_, false); // Reset all existing (very unusual: done for this demo)
draw_list->PushDrawFlag(scope_flags, true);
const ImDrawFlags flags = prim_stroke_flags | prim_other_flags;
const ImVec2 start_pos = ImGui::GetCursorScreenPos();
const float pi = 3.141592f;
const float step = sz + 10.0f;
const ImDrawFlags corners_tl_br = ImDrawFlags_RoundTopLeft | ImDrawFlags_RoundBottomRight;
const float half_sz = sz * 0.5f;
const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves
const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) };
float x = p.x + 4.0f;
float y = p.y + 4.0f;
for (int n = 0; n < 2; n++)
const ImVec2 cp3[3] = { { 0.0f, sz * 0.6f }, { sz * 0.5f, -sz * 0.4f }, { sz, sz } }; // Control points for curves
const ImVec2 cp4[4] = { { 0.0f, 0.0f }, { sz * 1.3f, sz * 0.3f }, { sz - sz * 1.3f, sz - sz * 0.3f }, { sz, sz } };
const ImVec2 concave_shape[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } }; // |_| looking shape. Normalized.
const ImVec2 zigzag_shape[] = { { 0.0f, 0.0f }, { 0.9f, 0.0f }, { 1.0f, 0.1f }, { 1.0f, 0.9f }, { 0.9f, 1.0f }, { 0.3f, 1.0f }, { 0.3f, 0.4f }, { 0.9f, 0.4f } };
ImVec2 rotating_square[4];
for (int side = 0; side < 4; side++)
{
// First line uses a thickness of 1.0f, second line uses the configurable thickness
float th = (n == 0) ? 1.0f : thickness;
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, 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, th, ImDrawFlags_Closed); x += sz + spacing; // Concave Shape
//draw_list->AddPolyline(concave_shape, IM_COUNTOF(concave_shape), col, ImDrawFlags_Closed, th);
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, th);
x += sz + spacing;
// Quadratic Bezier Curve (3 control points)
draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments);
x += sz + spacing;
// Cubic Bezier Curve (4 control points)
draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments);
x = p.x + 4;
y += sz + spacing;
float t = (float)ImGui::GetTime() * 0.1f + side * pi * 0.5f;
rotating_square[side] = { (float)cosf(t) * half_sz, (float)sinf(t) * half_sz };
}
// Filled shapes
draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon
draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle
draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), ImVec2(sz * 0.5f, sz * 0.3f), col, -0.3f, circle_segments); x += sz + spacing;// Ellipse
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners
draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle
//draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle
PathConcaveShape(draw_list, x, y, sz); draw_list->PathFillConcave(col); x += sz + spacing; // Concave shape
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine)
float x = start_pos.x;
float y = start_pos.y;
for (int row = 0; row < 4; row++)
{
x = start_pos.x;
bool draw_fill = (row == 2 || row == 3);
bool draw_strokes = (row == 0 || row == 1 || row == 3);
if (draw_fill)
{
// FILLED SHAPES
const ImU32 col = ImColor(colf_fill);
draw_list->AddNgonFilled({ x + half_sz, y + half_sz }, half_sz, col, ngon_segments); x += step; // N-gon
draw_list->AddCircleFilled({ x + half_sz, y + half_sz }, half_sz, col, circle_segments); x += step; // Circle
draw_list->AddEllipseFilled({ x + half_sz, y + half_sz }, { half_sz, sz * 0.3f }, col, -0.3f, circle_segments); x += step;// Ellipse
draw_list->AddRectFilled({ x, y }, { x + sz, y + sz }, col, 0.0f, flags); x += step; // Square
draw_list->AddRectFilled({ x, y }, { x + sz, y + sz }, col, rounding, flags); x += step; // Square with all rounded corners
draw_list->AddRectFilled({ x, y }, { x + sz, y + sz }, col, rounding, flags | corners_tl_br); x += step; // Square with two rounded corners
draw_list->AddTriangleFilled({ x + sz * 0.5f, y }, { x + sz, y + sz }, { x, y + sz }, col); x += step; // Triangle
draw_list->AddTriangleFilled({ x + sz * 0.2f, y }, { x + sz * 0.4f, y + sz }, { x, y + sz }, col); x += step - (float)(int)(sz * 0.6f); // Thin triangle
// Path
draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f);
draw_list->PathFillConvex(col);
x += sz + spacing;
// Concave shape: U
for (const ImVec2& p : concave_shape)
draw_list->PathLineTo({ x + (int)(sz * p.x), y + (int)(sz * p.y) });
draw_list->PathFillConcave(col);
x += step;
// Quadratic Bezier Curve (3 control points)
draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y));
draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments);
draw_list->PathFillConvex(col);
x += sz + spacing;
// Concave shape: Zig-Zag with sharp angles (see difference with/without JoinMiter)
for (const ImVec2& p : zigzag_shape)
draw_list->PathLineTo({ x + (int)(sz * p.x), y + (int)(sz * p.y) });
draw_list->PathFillConcave(col);
x += step;
draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
x += sz + spacing;
// Horizontal/Vertical lines
// (here for consistency with the strokes section. AddRectFilled() is roughly close to AddLineH(), AddLineV()
draw_list->AddRectFilled({ x, y }, { x + sz, y + thickness }, col); x += step;
draw_list->AddRectFilled({ x, y }, { x + thickness, y + sz }, col); x += step - (float)(int)half_sz;
if (!(draw_fill && draw_strokes)) //-V560
for (int block_sz = 1, off = 0; block_sz < 16 && off + block_sz <= sz; off += block_sz + 1, block_sz++)
draw_list->AddRectFilled({ x, y + off }, { x + block_sz, y + off + block_sz }, col);
x += step - (float)(int)half_sz;
// Rotating square
for (int n = 0; n < 4; n++)
draw_list->PathLineTo({ x + half_sz + rotating_square[n].x, y + half_sz + rotating_square[n].y });
draw_list->PathFillConvex(col, flags);
x += step;
// Path
draw_list->PathArcTo({ x + half_sz, y + half_sz }, half_sz, pi * -0.5f, pi * 1.1f);
draw_list->PathFillConvex(col);
x += step;
// Quadratic Bezier Curve (3 control points)
draw_list->PathLineTo({ x + cp3[0].x, y + cp3[0].y });
draw_list->PathBezierQuadraticCurveTo({ x + cp3[1].x, y + cp3[1].y }, { x + cp3[2].x, y + cp3[2].y }, curve_segments);
draw_list->PathFillConvex(col);
x += step;
if (!(draw_fill && draw_strokes)) //-V560
{
draw_list->AddRectFilledMultiColor({ x, y }, { x + sz, y + sz }, IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
x += step;
}
}
if (draw_fill && draw_strokes)
x = start_pos.x;
if (draw_strokes)
{
// STROKES
// First row uses a thickness of 1.0f, second row uses the configurable thickness
const ImU32 col = ImColor(colf_stroke);
float th = (row == 0) ? 1.0f : thickness;
draw_list->AddNgon({ x + half_sz, y + half_sz }, half_sz, col, ngon_segments, th, flags); x += step; // N-gon
draw_list->AddCircle({ x + half_sz, y + half_sz }, half_sz, col, circle_segments, th, flags); x += step; // Circle
draw_list->AddEllipse({ x + half_sz, y + half_sz }, { half_sz, sz * 0.3f }, col, -0.3f, circle_segments, th, flags); x += step; // Ellipse
draw_list->AddRect({ x, y }, { x + sz, y + sz }, col, 0.0f, th, flags); x += step; // Square
draw_list->AddRect({ x, y }, { x + sz, y + sz }, col, rounding, th, flags); x += step; // Square with all rounded corners
draw_list->AddRect({ x, y }, { x + sz, y + sz }, col, rounding, th, flags | corners_tl_br); x += step; // Square with two rounded corners
draw_list->AddTriangle({ x + sz * 0.5f, y }, { x + sz, y + sz }, { x, y + sz }, col, th, flags); x += step; // Triangle
draw_list->AddTriangle({ x + sz * 0.2f, y }, { x + sz * 0.4f, y + sz }, { x, y + sz }, col, th, flags); x += step - (float)(int)(sz * 0.6f); // Thin triangle
// Concave shape: U
for (const ImVec2& p : concave_shape)
draw_list->PathLineTo({ x + (int)(sz * p.x), y + (int)(sz * p.y) });
draw_list->PathStroke(col, th, flags | ImDrawFlags_Closed);
x += step;
// Concave shape: Zig-Zag with sharp angles (see difference with/without JoinMiter)
for (const ImVec2& p : zigzag_shape)
draw_list->PathLineTo({ x + (int)(sz * p.x), y + (int)(sz * p.y) });
draw_list->PathStroke(col, th, flags | ImDrawFlags_Closed);
x += step;
// Horizontal/Vertical/Diagonal lines
const float off = (float)(int)(sz * 0.4f);
draw_list->AddLineH(x, x + sz, y, col, th, flags);
draw_list->AddLine({ x, y + off }, { x + sz, y + off }, col, th, flags);
x += step;
draw_list->AddLineV(x, y, y + sz, col, th, flags);
draw_list->AddLine({ x + off, y + sz }, { x + off, y }, col, th, flags);
x += step - (float)(int)half_sz;
if (!(draw_fill && draw_strokes)) //-V560
{
draw_list->AddLine({ x, y }, { x + half_sz, y + sz }, col, th, flags);
draw_list->AddLine({ x, y + sz }, { x + half_sz, y }, col, th, flags);
}
x += step - (float)(int)half_sz;
// Rotating square
for (int n = 0; n < 4; n++)
draw_list->PathLineTo({ x + half_sz + rotating_square[n].x, y + half_sz + rotating_square[n].y });
draw_list->PathStroke(col, th, flags | ImDrawFlags_Closed);
//for (int n = 0; n < 4; n++) // ...made of individual line
// draw_list->AddLine({ x + half_sz + rotating_square[n].x, y + half_sz + rotating_square[n].y }, { x + half_sz + rotating_square[(n + 1) & 3].x, y + half_sz + rotating_square[(n + 1) & 3].y }, col, th, flags);
x += step;
// Path
draw_list->PathArcTo({ x + half_sz, y + half_sz }, half_sz, pi * -0.5f, pi * 1.1f);
draw_list->PathStroke(col, th, flags);
x += step;
// Quadratic Bezier Curve (3 control points)
draw_list->AddBezierQuadratic({ x + cp3[0].x, y + cp3[0].y }, { x + cp3[1].x, y + cp3[1].y }, { x + cp3[2].x, y + cp3[2].y }, col, th, curve_segments, flags);
x += step;
// Cubic Bezier Curve (4 control points)
if (!(draw_fill && draw_strokes)) //-V560
{
draw_list->AddBezierCubic({ x + cp4[0].x, y + cp4[0].y }, { x + cp4[1].x, y + cp4[1].y }, { x + cp4[2].x, y + cp4[2].y }, { x + cp4[3].x, y + cp4[3].y }, col, th, curve_segments, flags);
x += step;
}
}
y += step;
}
ImGui::Dummy(ImVec2(step * 15.5f, step * 4.0f));
draw_list->PopDrawFlag();
draw_list->PopDrawFlag();
ImGui::Text("ImDrawList Vector Rendering Reference:");
ImGui::TextLinkOpenURL("https://github.com/ocornut/imgui/wiki/Draw-List");
ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f));
ImGui::PopItemFlag();
ImGui::PopItemWidth();
ImGui::EndTabItem();
@ -10731,9 +10871,9 @@ static void ShowExampleAppCustomRendering(bool* p_open)
ImGui::Text("Blue shape is drawn first: appears in back");
ImGui::Text("Red shape is drawn after: appears in front");
ImVec2 p0 = ImGui::GetCursorScreenPos();
draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25), ImVec2(p0.x + 75, p0.y + 75), IM_COL32(255, 0, 0, 255)); // Red
ImGui::Dummy(ImVec2(75, 75));
draw_list->AddRectFilled({ p0.x, p0.y }, { p0.x + 50, p0.y + 50 }, IM_COL32(0, 0, 255, 255)); // Blue
draw_list->AddRectFilled({ p0.x + 25, p0.y + 25 }, { p0.x + 75, p0.y + 75 }, IM_COL32(255, 0, 0, 255)); // Red
ImGui::Dummy({ 75, 75 });
}
ImGui::Separator();
{
@ -10745,14 +10885,14 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// You can create any number of channels. Tables API use 1 channel per column in order to better batch draw calls.
draw_list->ChannelsSplit(2);
draw_list->ChannelsSetCurrent(1);
draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
draw_list->AddRectFilled({ p1.x, p1.y }, { p1.x + 50, p1.y + 50 }, IM_COL32(0, 0, 255, 255)); // Blue
draw_list->ChannelsSetCurrent(0);
draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25), ImVec2(p1.x + 75, p1.y + 75), IM_COL32(255, 0, 0, 255)); // Red
draw_list->AddRectFilled({ p1.x + 25, p1.y + 25 }, { p1.x + 75, p1.y + 75 }, IM_COL32(255, 0, 0, 255)); // Red
// Flatten/reorder channels. Red shape is in channel 0 and it appears below the Blue shape in channel 1.
// This works by copying draw indices only (vertices are not copied).
draw_list->ChannelsMerge();
ImGui::Dummy(ImVec2(75, 75));
ImGui::Dummy({ 75, 75 });
ImGui::Text("After reordering, contents of channel 0 appears below channel 1.");
}
ImGui::EndTabItem();

File diff suppressed because it is too large Load Diff

View File

@ -517,13 +517,23 @@ inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : (x > 0.0f
inline double ImSign(double x) { return (x < 0.0) ? -1.0 : (x > 0.0) ? 1.0 : 0.0; }
#ifdef IMGUI_ENABLE_SSE
inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
// Converge to more precise solution using single step of Newton-Raphson method, repeating increases precision
inline float ImRsqrtPrecise(float x) { const float r = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); return r * (1.5f - x * 0.5f * r * r); }
#else
inline float ImRsqrt(float x) { return 1.0f / sqrtf(x); }
inline float ImRsqrtPrecise(float x) { return 1.0f / sqrtf(x); }
#endif
inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
#endif
// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double
// (Exceptionally using templates here but we could also redefine them for those types)
// (Specialized version ensure that runtime-check pragmas/macros are applied with caller settings. Template version are less reliable in this regards)
inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
template<typename T> T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
template<typename T> T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
template<typename T> T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
@ -559,6 +569,23 @@ inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x
inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / (float)n; avg += sample / (float)n; return avg; }
inline bool ImIsTruncated(float x) { return (float)(int)x == x; }
#ifdef IMGUI_ENABLE_SSE
// Returns true if all parameters are whole numbers.
inline bool ImIsTruncated4(float x, float y, float z, float w)
{
__m128 v = _mm_set_ps(x, y, z, w);
__m128i i = _mm_cvttps_epi32(v);
return _mm_movemask_ps(_mm_cmpeq_ps(v, _mm_cvtepi32_ps(i))) == 0xF;
}
#else
inline bool ImIsTruncated4(float x, float y, float z, float w)
{
return (float)(int)x == x && (float)(int)y == y && (float)(int)z == z && (float)(int)w == w;
}
#endif
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helpers: Geometry
@ -901,11 +928,28 @@ IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStorag
#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(_N,_MAXERROR) ((_MAXERROR) / (1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))))
#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_ERROR(_N,_RAD) ((1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))) / (_RAD))
// ImDrawList: Lookup table size for adaptive arc drawing, cover full circle.
// ImDrawList: Lookup tables
#ifndef IM_DRAWLIST_ARCFAST_TABLE_SIZE
#define IM_DRAWLIST_ARCFAST_TABLE_SIZE 48 // Number of samples in lookup table.
#define IM_DRAWLIST_ARCFAST_TABLE_SIZE (48) // Number of samples in adaptive arc drawing lookup table.
#endif
#define IM_DRAWLIST_ARCFAST_SAMPLE_MAX IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle.
#define IM_DRAWLIST_ARCFAST_SAMPLE_MAX IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle.
#ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX
#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (32) // The maximum line width to bake anti-aliased textures for.
#endif
#ifndef IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH
#define IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH (4) // Calculate detailed textures for width [1..IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH]
#endif
#ifndef IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT
#define IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT (4) // How many samples per integer thickness level.
#endif
#ifndef IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX
#define IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX (16)
#endif
#ifndef IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX
#define IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX (4) // 0: fill, 1-3: strokes thickness
#endif
#define IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_COUNT ((IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH - 1) * IM_DRAWLIST_TEX_LINES_SAMPLE_COUNT + 1)
// Data shared between all ImDrawList instances
// Conceptually this could have been called e.g. ImDrawListSharedContext
@ -914,14 +958,15 @@ IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStorag
struct IMGUI_API ImDrawListSharedData
{
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas (== FontAtlas->TexUvWhitePixel)
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas (== FontAtlas->TexUvLines)
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas (== FontAtlas->Builder->TexUvLines)
const ImVec4* TexUvCorners; // UV of rounded corner (== FontAtlas->Builder->TexUvCorners)
ImFontAtlas* FontAtlas; // Current font atlas
ImFont* Font; // Current font (used for simplified AddText overload)
float FontSize; // Current font size (used for simplified AddText overload)
float FontScale; // Current font scale (== FontSize / Font->FontSize)
float CurveTessellationMaxError; // Tessellation tolerance when using PathBezierCurveTo()
float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
ImDrawFlags InitialDrawFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
ImVector<ImVec2> TempBuffer; // Temporary write buffer
ImVector<ImDrawList*> DrawLists; // All draw lists associated to this ImDrawListSharedData
@ -4335,8 +4380,14 @@ struct ImFontAtlasBuilder
// Custom rectangle identifiers
ImFontAtlasRectId PackIdMouseCursors; // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
ImFontAtlasRectId PackIdLinesTexData;
ImFontAtlasRectId PackIdLineFractTexData;
ImFontAtlasRectId PackIdCornersTexData;
ImFontAtlasBuilder() { memset((void*)this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = -1; }
// Cached UV coordinates
ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1 + IM_DRAWLIST_TEX_LINES_DETAILED_WIDTH_COUNT]; // UVs for baked anti-aliased lines (u0, u1, v, 1/thickness)
ImVec4 TexUvCorners[IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX * IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX]; // UVs for baked anti-aliased corners (0= fill, 1> stroke thickness)
ImFontAtlasBuilder() { memset((void*)this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = PackIdLineFractTexData = PackIdCornersTexData = -1; }
};
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);

View File

@ -2961,7 +2961,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
// Draw inner border and resizing feedback
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float border_size = TABLE_BORDER_SIZE;
const float draw_y1 = ImMax(table->InnerRect.Min.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight) + ((table->Flags & ImGuiTableFlags_BordersOuterH) ? 1.0f : 0.0f);
const float draw_y1 = ImMax(table->InnerRect.Min.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight) + ((table->Flags & ImGuiTableFlags_BordersOuterH) ? border_size : 0.0f);
const float draw_y2_body = table->InnerRect.Max.y;
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastTopHeadersRowHeight) : draw_y1;
if (table->Flags & ImGuiTableFlags_BordersInnerV)
@ -3018,7 +3018,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
{
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);
inner_drawlist->AddLineV(outer_border.Max.x - border_size, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
{
@ -3029,9 +3029,10 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
{
// Draw bottom-most row border between it is above outer border.
const float h_inset = (table->Flags & ImGuiTableFlags_BordersOuterV) ? border_size : 0.0f;
const float border_y = table->RowPosY2;
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
inner_drawlist->AddLineH(table->BorderX1, table->BorderX2, border_y, table->BorderColorLight, border_size);
inner_drawlist->AddLineH(table->BorderX1 + h_inset, table->BorderX2 - h_inset, border_y, table->BorderColorLight, border_size);
}
inner_drawlist->PopClipRect();
@ -3624,7 +3625,8 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
if (pass == 1)
{
// Draw border
draw_list->AddLine(bg_shape[0] - ImVec2(TABLE_BORDER_SIZE * 0.5f, 0.0f), bg_shape[3] - ImVec2(TABLE_BORDER_SIZE * 0.5f, 0.0f), TableGetColumnBorderCol(table, order_n, column_n), TABLE_BORDER_SIZE);
const float border_size = TABLE_BORDER_SIZE;
draw_list->AddLine(bg_shape[0] + ImVec2(border_size * 0.5f, 0.0f), bg_shape[3] + ImVec2(border_size * 0.5f, 0.0f), TableGetColumnBorderCol(table, order_n, column_n), border_size);
}
}
PopClipRect();

View File

@ -932,7 +932,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
const ImVec2 cross_center = bb.GetCenter();
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
const float cross_thickness = 1.0f * (float)(int)g.Style._MainScale; // FIXME-DPI
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
@ -1764,7 +1764,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
const float sep1_x1 = pos.x;
const float sep2_x2 = bb.Max.x;
const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.999f);
float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f) + 1.0f;
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
@ -1778,9 +1778,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->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
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);
@ -1790,7 +1790,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
if (g.LogEnabled)
LogText("---");
if (separator_thickness > 0.0f)
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness);
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness, ImDrawFlags_StrokeCenterBiased);
}
}
@ -1987,12 +1987,12 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
RenderNavCursor(bb, id);
if (!(flags & ImGuiComboFlags_NoPreview))
window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundAll : ImDrawFlags_RoundLeft);
if (!(flags & ImGuiComboFlags_NoArrowButton))
{
ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text);
window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundAll : ImDrawFlags_RoundRight);
if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x)
RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
}
@ -5766,9 +5766,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->CursorAnim += io.DeltaTime;
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
ImRect cursor_screen_rect = ImRect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 1.0f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.0f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize);
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize, ImDrawFlags_StrokeInside);
// 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.
@ -6630,10 +6630,10 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
{
float mid_x = IM_ROUND((bb.Min.x + bb.Max.x) * 0.5f);
if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, ColorConvertFloat4ToU32(col_rgb), g.Style.Alpha, grid_step, ImVec2(-grid_step, 0.0f), rounding, ImDrawFlags_RoundCornersRight);
RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, ColorConvertFloat4ToU32(col_rgb), g.Style.Alpha, grid_step, ImVec2(-grid_step, 0.0f), rounding, ImDrawFlags_RoundRight);
else
window->DrawList->AddRectFilled(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundCornersRight);
window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft);
window->DrawList->AddRectFilled(ImVec2(bb.Min.x + grid_step, bb.Min.y), bb.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundRight);
window->DrawList->AddRectFilled(bb.Min, ImVec2(mid_x, bb.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundLeft);
}
else
{
@ -7315,17 +7315,19 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
if ((window->DC.TreeHasStackDataDepthMask & TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth - 1)) == 0)
return;
// FIXME: Could this be simplified using new stroke flags?
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
float x1 = ImTrunc(parent_data->DrawLinesX1);
const float half_size = g.Style.TreeLinesSize * 0.5f;
float x1 = ImTrunc(parent_data->DrawLinesX1 - half_size) + half_size; // Draw line centered at X1, but snap to pixels boundary.
float x2 = ImTrunc(target_pos.x - g.Style.ItemInnerSpacing.x);
float y = ImTrunc(target_pos.y);
float y = ImTrunc(target_pos.y - half_size) + half_size;
float rounding = (g.Style.TreeLinesRounding > 0.0f) ? ImMin(x2 - x1, g.Style.TreeLinesRounding) : 0.0f;
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, y - rounding);
if (x1 >= x2)
return;
if (rounding > 0.0f)
if (rounding > 0.0f && rounding > half_size)
{
x1 += 0.5f + rounding;
x1 += rounding;
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
if (x1 < x2)
window->DrawList->PathLineTo(ImVec2(x2, y));
@ -7333,7 +7335,10 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
}
else
{
window->DrawList->AddLineH(x1, x2, y, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
// We use AddLine() instead of AddLineH() as we provide coordinates for line center,
// in order to make the code use same coordinates for both rounded and non-rounded version. (FIXME-OPT)
x1 += half_size; // Avoid overdraw
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
}
}
@ -7356,10 +7361,12 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
y2 = ImMin(y2, window->ClipRect.Max.y);
if (y2 <= y1)
return;
float x = ImTrunc(data->DrawLinesX1);
float x = ImTrunc(data->DrawLinesX1 - g.Style.TreeLinesSize * 0.5f) + g.Style.TreeLinesSize * 0.5f; // Draw line centered at X1, but snap to pixels boundary.
if (data->DrawLinesTableColumn != -1)
TablePushColumnChannel(data->DrawLinesTableColumn);
window->DrawList->AddLineV(x, y1, y2, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
// We use AddLine() instead of AddLineV() as we provide coordinates for line center (FIXME-OPT)
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
if (data->DrawLinesTableColumn != -1)
TablePopColumnChannel();
}
@ -11055,8 +11062,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f)
{
// Might be moved to TabItemBackground() ?
ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale);
ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale);
ImVec2 tl = bb.GetTL() + ImVec2(0, style.TabBarOverlineSize * 0.5f);
ImVec2 tr = bb.GetTR() + ImVec2(0, style.TabBarOverlineSize * 0.5f);
ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline);
if (style.TabRounding > 0.0f)
{
@ -11067,7 +11074,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
}
else
{
display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize);
display_draw_list->AddLine(tl, tr, overline_col, style.TabBarOverlineSize);
}
}
RenderNavCursor(bb, id);
@ -11170,14 +11177,14 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
const float y1 = bb.Min.y + 1.0f; // Leave a bit of room in title bars.
const float y2 = bb.Max.y - g.Style.TabBarBorderSize;
draw_list->AddRectFilled(bb.Min, ImVec2(bb.Max.x, y2), col, rounding, ImDrawFlags_RoundCornersTop);
draw_list->AddRectFilled(ImVec2(bb.Min.x, y1), ImVec2(bb.Max.x, y2), col, rounding, ImDrawFlags_RoundTop);
if (g.Style.TabBorderSize > 0.0f)
{
draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
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), g.Style.TabBorderSize);
draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), g.Style.TabBorderSize, ImDrawFlags_StrokeCenterBiased); // Use _StrokeInside?
}
}