mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-11-02 12:31:06 +01:00
3rdparty/imgui: Update to v1.93.0
Signed-off-by: SternXD <stern@sidestore.io>
This commit is contained in:
1 parent
05f3cf3eae
commit
15bf641bfe
14 files changed
+3901
-1259
No files matched your search
Vendored
+415
-3
@@ -39,6 +39,418 @@ HOW TO UPDATE?
|
||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.93.0 (Released 2026-10-14)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.93.0
|
||||
|
||||
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 which graphics API is used
|
||||
(note that using _StrokeLegacy mode can lead to the same old 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
|
||||
|
||||
Don't panic!
|
||||
Many applications will not notice any difference! You will more likely see
|
||||
differences if you used lots of direct `ImDrawList` calls for custom rendering.
|
||||
|
||||
Credits for ImDrawList changes in 1.93.0:
|
||||
- main work courtesy of @memononen.
|
||||
- additional work/reviewing/guidance by @ocornut.
|
||||
- with legacy bits from @thedmd, @potocpav.
|
||||
Other credits marked below, or @ocornut when omitted.
|
||||
|
||||
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 compare differences between 1.92.9 and 1.93.0 + commentary)
|
||||
(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
|
||||
- Discussion topic:
|
||||
https://github.com/ocornut/imgui/issues/9504
|
||||
(if you have a problem to discuss, please open a new issue)
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- ImDrawList:
|
||||
- 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 `ImDrawFlags_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.
|
||||
- `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.
|
||||
- style.CurveTessellationMaxError == sqrtf(style.CurveTessellationTol).
|
||||
- ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`:
|
||||
prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
|
||||
- Fonts: renamed `AddRemapChar()` to `AddRemapCodepoint()` (rarely used, marked internal).
|
||||
(#609, #5748, #9559)
|
||||
- Backends:
|
||||
- DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was
|
||||
obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support
|
||||
for `ImGuiBackendFlags_RendererHasTextures`. Use the new signature! (#9487)
|
||||
- OpenGL3: Does not attempt to read `GL_CLIP_ORIGIN` by default as the detection is
|
||||
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:
|
||||
|
||||
- Style:
|
||||
- StyleColorsDark(): minor refresh of the default style to look more modern:
|
||||
- Changed WindowBg to use a slightly greyer value and removed opacity.
|
||||
- Changed FrameBg values to use a dark black to make frames stand out better.
|
||||
- Tweak TextDisabled, TableHeaderBg, TableBorders to match altered WindowBg.
|
||||
- StyleColorsLight(): inverted `ImGuiCol_TitleBgXXX` colors so that the selected
|
||||
window title bar appears brighter.
|
||||
- ImDrawList:
|
||||
- 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 beveled 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 drawlists.
|
||||
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 beveled 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. (#9577)
|
||||
- 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]
|
||||
- Mixed Values:
|
||||
- Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values.
|
||||
Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX()
|
||||
and Combo() functions.
|
||||
The scoped flag is designed for usage by advanced property editors. (#5518, #5677, #6865)
|
||||
- Drags, Sliders:
|
||||
- Ongoing drags may be cancelled using Right-Click, Escape or Gamepad Triangle.
|
||||
Cancelling reverts to the initial value. (#8564, #9534)
|
||||
- Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
|
||||
leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
|
||||
- TreeNode:
|
||||
- Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
|
||||
features or other features requiring stack storage. (#9509) [@lasrod]
|
||||
- TabBar:
|
||||
- Improved scroll target when clicking a Tab that is larger than the scrolling
|
||||
section width.
|
||||
- Using <> scrolling buttons while the selected Tab is at either end of the
|
||||
section mid-section but not fully visible always makes it fully visible
|
||||
(before eventually selecting a Tab in the leading/trailing section).
|
||||
- Tables:
|
||||
- Fixed a bug restoring correct .ini columns order when table use is Sortable
|
||||
but had no user changes. (regression from 1.92.9). (#9519, #9108)
|
||||
- Fixed a bug tracking topology changes (insert new columns in the middle)
|
||||
when the table is not _Reorderable: new columns would be ordered incorrectly.
|
||||
(#9570, #9108, #9572) [@lailoken]
|
||||
- InputText:
|
||||
- Fixed a crash in some cases when using Home key in a WordWrap+ReadOnly field. (#9561)
|
||||
- Selectable:
|
||||
- Fixed `ImGuiSelectableFlags_SelectOnNav` triggering during NavInit.
|
||||
- Fonts:
|
||||
- Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic
|
||||
to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of
|
||||
ProggyClean on most Apple/Retina setups by default.
|
||||
- Added `ImFont::AddRemapCodepointToGlyphIndex()` allowing to access glyphs that are not
|
||||
mapped to codepoints. (#9559, #5647, #609, #5748, #8466)
|
||||
- imgui_freetype: Fixed blurriness rendering `AddFontDefaultVector()`. Caused by a
|
||||
non-pixel aligned offset caused by `ExtraSizeScale`. (#9348, #9233) [@redpartizan, @RDMCz]
|
||||
- (Internal) ImFontLoader: reworked `FontSrcContainsGlyph`, `FontBakedLoadGlyph` signatures
|
||||
to take raw glyph index instead of codepoint. Added `FontSrcGetGlyphIndexFromCodepoint`.
|
||||
(#9559, #5647, #9540, #8466, #8465)
|
||||
- Added `IMGUI_DISABLE_STB_TRUETYPE` to completely omit the stb_truetype loader
|
||||
code + stb_truetype.h code. (#9573)
|
||||
- ColorEdit:
|
||||
- ColorButton, ColorEdit, ColorPicker: cancel-out alpha caused by `BeginDisabled()` so
|
||||
disabled color buttons have the same color as non-disabled oness. (#9511)
|
||||
- ColorButton: fixed issues/inconsistencies with checkerboard rendering when combining
|
||||
color alpha and global style alpha. (#9511) [@enjmiah, @ocornut]
|
||||
- Popups:
|
||||
- Amended context menu right-click opening code to check that the right-click
|
||||
hasn't been owned by another items. This is more correct and also necessary
|
||||
to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
|
||||
- Reworked `GetMousePosOnOpeningCurrentPopup()` to be legal to call within the
|
||||
BeginPopup/EndPopup scope of a popup which was just closed. (#9551) [@jkunstwald]
|
||||
- ImGuiTextFilter:
|
||||
- Added support for space as an "and" filter, which is the standard. (#2435, #30)
|
||||
e.g. w/ filter 'hello world' (without quotes) both words needs to be in input data.
|
||||
- Added support for double-quoted "xxx" blocks to e.g. match words sequences. (#2435)
|
||||
e.g. w/ filter "hello world" the exact sequence needs to be in input data.
|
||||
- Fixed filtering when mixing "include" and "-exclude" keyword so that an "-exclude"
|
||||
match always filters out. (#2435) [@kudaba, @ocornut]
|
||||
- Added `DrawWithHint()` function. (#6206, #6395, #6447)
|
||||
- Added a "incl -excl" hint by default when the search field is empty. (#6206, #6395, #6447)
|
||||
- Widgets:
|
||||
- Checkbox, Menus: check marks use anti-aliased ends.
|
||||
- Tweaked rendering in various locations to avoid blurriness:
|
||||
- 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).
|
||||
- Misc:
|
||||
- Fixed `GetBackgroundDrawList()`/`GetForegroundDrawList()` not being properly reset
|
||||
every frame when accumulated session time is very large (e.g. a few days). [@lailoken]
|
||||
- Added `IM_NODEBUGSTEP` helper to tag functions with `__declspec(non_user_code)` (MSVC)
|
||||
or `[[gnu::artificial]]` (Clang/GCC) in order to provide a hint to debuggers to skip
|
||||
trivial functions when stepping into.
|
||||
- Tagged various trivial functions using `IM_NODEBUGSTEP`: `ImVec2()`, `ImVec4()` etc.
|
||||
and various operators.
|
||||
- Fixed strict aliasing violation in `ImHashData()` affecting Clang 23 + SSE 4.2 + -flto.
|
||||
Could manifest as `ImFontAtlasBakedGetId()` computation omitting font size from
|
||||
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]
|
||||
- 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 resetting all states
|
||||
in the glTexParameter() path. (#9378)
|
||||
- OpenGL3: added `ImGui_ImplOpenGL3_SetClipOrigin()` to specify origin between
|
||||
`GL_LOWER_LEFT` (new default), `GL_UPPER_LEFT` and `0` (autodetect, old default).
|
||||
- OpenGL3: avoid querying `glGetIntegerv(GL_CLIP_ORIGIN)` multiple times when using
|
||||
when using default and using `DrawCallback_ResetRenderState`, at it appear to stall
|
||||
some drivers. (#2186, #3998, #3146, #3143, #8640)
|
||||
- SDL2: fixed querying framebuffer scale/density when using Metal without
|
||||
going through a SDL_Renderer. (#5592) [@lailoken]
|
||||
- SDLRenderer3: restore any temporarily modified texture scale modes at the of `RenderDrawData()`. (#9378)
|
||||
- SDLRenderer3: expose CurrentScaleMode in ImGui_ImplSDLRenderer3_RenderState. (#9543, #9378) [@Clownacy]
|
||||
- SDLRenderer3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw callback to request
|
||||
using the sampler associated already associated to a texture via `SDL_SetTextureScaleMode()`. (#9378)
|
||||
It is equivalent to setting `render_state->CurrentScaleMode = SDL_SCALEMODE_INVALID`.
|
||||
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]
|
||||
- Examples:
|
||||
- All: all examples now default to use a little bit of rounding (`FrameRounding` and `GrabRounding`).
|
||||
- MSVC: disabled /JMC in Visual Studio projects (unnecessary overhead).
|
||||
- GLFW/SDL2/SDL3+WebGPU: fixed running with wgpu-native missing `wgpuInstanceWaitAny()`. (#9377)
|
||||
- GLFW/SDL2/SDL3+WebGPU: better select surface format. (#9576) [@ypujante]
|
||||
- GLFW+Metal: fixed mistakenly calling `ImGui_ImplGlfw_InitForOpenGL()`, which
|
||||
broke multi-viewport support. (#9564) [@ypujante]
|
||||
- SDL2+Metal: create Metal context without using a `SDL_Renderer`.
|
||||
- QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry]
|
||||
- OSX+OpenGL3: added example_apple_opengl3/ (OSX/Cocoa + OpenGL 3.2 Core profile).
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.9b (Released 2026-07-31)
|
||||
-----------------------------------------------------------------------
|
||||
@@ -1639,7 +2051,7 @@ Non-breaking Fonts/Textures related changes:
|
||||
- Fonts: ImFontAtlas::AddFontXXX() can fail more gracefully if error handling is configured
|
||||
to not assert (this will be better exposed via future font flags).
|
||||
- Fonts: added style.FontScaleBase scaling factor (previously called io.FontGlobalScale).
|
||||
- Fonts: added style.FontScaleDpi scaling factor. This is designed to be be changed on
|
||||
- Fonts: added style.FontScaleDpi scaling factor. This is designed to be changed on
|
||||
per-monitor/per-viewport basis, which `io.ConfigDpiScaleFonts` does automatically.
|
||||
(which is why it is separate from FontScaleBase).
|
||||
- Fonts: added optional font_size parameter to ImGui::PushFont() function.
|
||||
@@ -2794,7 +3206,7 @@ Other changes:
|
||||
- Backends: Vulkan: Remove Volk/ from volk.h #include directives. (#7722, #6582, #4854)
|
||||
[@martin-ejdestig]
|
||||
- Examples: SDL3: Remove use of SDL_HINT_IME_NATIVE_UI since new SDL_HINT_IME_IMPLEMENTED_UI
|
||||
values has a more suitable default for our case case.
|
||||
values has a more suitable default for our case.
|
||||
- Examples: GLFW+Vulkan, SDL+Vulkan: handle swap chain resize even without Vulkan
|
||||
returning VK_SUBOPTIMAL_KHR, which doesn't seem to happen on Wayland. (#7671)
|
||||
[@AndreiNego, @ocornut]
|
||||
@@ -4747,7 +5159,7 @@ Other Changes:
|
||||
- ColorPicker4: Fixed picker being unable to select exact 1.0f color when dragging toward the edges
|
||||
of the SV square (previously picked 0.999989986f). (#3517) [@rokups]
|
||||
- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar (broken in 1.84). (#4538)
|
||||
- Menus: Improve closing logic when moving diagonally in empty between between parent and child menus to
|
||||
- Menus: Improve closing logic when moving diagonally in empty space between parent and child menus to
|
||||
accommodate for varying font size and dpi.
|
||||
- Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510).
|
||||
- Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640)
|
||||
|
||||
Vendored
+12
-7
@@ -72,7 +72,8 @@
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version.
|
||||
// This is for if you already embed a copy of those library in your code and don't want duplicate code in your binary.
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
@@ -102,20 +103,24 @@
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
IM_NODEBUGSTEP inline operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
IM_NODEBUGSTEP constexpr inline ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
IM_NODEBUGSTEP inline operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//---- ...Or use Dear ImGui's own basic math operators in every file including imgui.h:
|
||||
//#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
//#endif
|
||||
//---- ...Or manually '#define IMGUI_DEFINE_MATH_OPERATORS' before '#include "imgui.h"' to use from one file.
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
|
||||
Vendored
+252
-146
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.92.9b"
|
||||
#define IMGUI_VERSION_NUM 19291
|
||||
#define IMGUI_VERSION "1.93.0"
|
||||
#define IMGUI_VERSION_NUM 19300
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
|
||||
@@ -49,7 +49,7 @@ Index of this file:
|
||||
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, 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)
|
||||
@@ -128,6 +128,16 @@ Index of this file:
|
||||
#define IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
#endif
|
||||
|
||||
// Alternative to using a .natstepfilter file or other scripts in misc/debuggers/ to skip debug-stepping selected trivial functions.
|
||||
// If you get a compiler error or warning related to use, please report it to us!
|
||||
#if (defined(__clang__) && (__clang_major__ >= 7)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
|
||||
#define IM_NODEBUGSTEP [[gnu::artificial]]
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1915)
|
||||
#define IM_NODEBUGSTEP __declspec(non_user_code)
|
||||
#else
|
||||
#define IM_NODEBUGSTEP
|
||||
#endif
|
||||
|
||||
// Warnings
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
@@ -236,7 +246,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
|
||||
@@ -294,11 +303,11 @@ typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data);
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
struct ImVec2
|
||||
{
|
||||
float x, y;
|
||||
constexpr ImVec2() : x(0.0f), y(0.0f) { }
|
||||
constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { }
|
||||
float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine.
|
||||
float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; }
|
||||
float x, y;
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2() : x(0.0f), y(0.0f) { }
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2(float _x, float _y) : x(_x), y(_y) { }
|
||||
float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine.
|
||||
float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; }
|
||||
#ifdef IM_VEC2_CLASS_EXTRA
|
||||
IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2.
|
||||
#endif
|
||||
@@ -307,9 +316,9 @@ struct ImVec2
|
||||
// ImVec4: 4D vector used to store clipping rectangles, colors etc. [Compile-time configurable type]
|
||||
struct ImVec4
|
||||
{
|
||||
float x, y, z, w;
|
||||
constexpr ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
|
||||
constexpr ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { }
|
||||
float x, y, z, w;
|
||||
IM_NODEBUGSTEP constexpr inline ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
|
||||
IM_NODEBUGSTEP constexpr inline ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { }
|
||||
#ifdef IM_VEC4_CLASS_EXTRA
|
||||
IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
|
||||
#endif
|
||||
@@ -983,7 +992,7 @@ namespace ImGui
|
||||
IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true!
|
||||
IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. returns NULL when drag and drop is finished or inactive. use ImGuiPayload::IsDataType() to test for the payload type.
|
||||
|
||||
// Disabling [BETA API]
|
||||
// Disabling
|
||||
// - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
|
||||
// - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
|
||||
// - Tooltips windows are automatically opted out of disabling. Note that IsItemHovered() by default returns false on disabled items, unless using ImGuiHoveredFlags_AllowWhenDisabled.
|
||||
@@ -1100,7 +1109,7 @@ namespace ImGui
|
||||
// - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them.
|
||||
// - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function.
|
||||
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
|
||||
|
||||
// Inputs Utilities: Mouse
|
||||
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
|
||||
@@ -1261,6 +1270,17 @@ enum ImGuiItemFlags_
|
||||
ImGuiItemFlags_LiveEditOnInputText = 1 << 7, // true // InputText: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
|
||||
ImGuiItemFlags_LiveEditOnInputScalar = 1 << 8, // false // DragXXX, SliderXXX, InputScalar: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
|
||||
ImGuiItemFlags_LiveEditOnInput = ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar,
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// [BETA] MixedValue mode used to represent a mixed/indeterminate state, typically for multi-selection.
|
||||
// - Replace value display with "-" or a custom label.
|
||||
// - Enter key validation apply an edit and return true even if value hasn't changed (in order to apply to all).
|
||||
// - Supported by selected widgets: Checkbox, RadioButton, Sliders, Drags, Inputs, Combo.
|
||||
// - Note: InputText-side Undo cannot be reliably combined with MixedValue + LiveEdit On:
|
||||
// - Both the initial edit and subsequent undo/revert will typically make your app code write to all backing objects.
|
||||
// - If you use MixedMode and the simplest solution is to ensure LiveEdit is off but widgets where this applies.
|
||||
//---------------------------------------------------------------------------------
|
||||
ImGuiItemFlags_MixedValue = 1 << 9, // false // [BETA] Represent a mixed/indeterminate value. Replace value label with "-" and apply edits on validation.
|
||||
};
|
||||
|
||||
// Flags for ImGui::InputText()
|
||||
@@ -2259,13 +2279,13 @@ struct ImVector
|
||||
inline int size_in_bytes() const { return Size * (int)sizeof(T); }
|
||||
inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); }
|
||||
inline int capacity() const { return Capacity; }
|
||||
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
|
||||
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
|
||||
IM_NODEBUGSTEP inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
|
||||
IM_NODEBUGSTEP inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
|
||||
|
||||
inline T* begin() { return Data; }
|
||||
inline const T* begin() const { return Data; }
|
||||
inline T* end() { return Data + Size; }
|
||||
inline const T* end() const { return Data + Size; }
|
||||
IM_NODEBUGSTEP inline T* begin() { return Data; }
|
||||
IM_NODEBUGSTEP inline const T* begin() const { return Data; }
|
||||
IM_NODEBUGSTEP inline T* end() { return Data + Size; }
|
||||
IM_NODEBUGSTEP inline const T* end() const { return Data + Size; }
|
||||
inline T& front() { IM_ASSERT(Size > 0); return Data[0]; }
|
||||
inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; }
|
||||
inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; }
|
||||
@@ -2356,7 +2376,7 @@ struct ImGuiStyle
|
||||
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
|
||||
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
||||
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
|
||||
float MenuItemRounding; // Radius of MenuItem, BeginMenu rounding.
|
||||
float MenuItemRounding; // Radius of MenuItem, BeginMenu rounding.
|
||||
float SelectableRounding; // Radius of Selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589)
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
|
||||
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
|
||||
@@ -2373,10 +2393,12 @@ struct ImGuiStyle
|
||||
ImVec2 DisplayWindowPadding; // Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen.
|
||||
ImVec2 DisplaySafeAreaPadding; // Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).
|
||||
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). We apply per-monitor DPI scaling over this scale. May be removed later.
|
||||
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).
|
||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
|
||||
|
||||
// Rendering & Tessellation
|
||||
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.
|
||||
|
||||
// Colors
|
||||
@@ -2400,6 +2422,8 @@ 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
|
||||
};
|
||||
@@ -2535,6 +2559,12 @@ 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(ImDrawFlags_StrokeLegacy,true) on every draw list instances.
|
||||
// - Suggested use, e.g. io.ConfigDebugDrawListDefaultsToStrokeLegacy = io.KeyShift; // Map to SHIFT modifier
|
||||
// - Also see our interactive testbed: https://www.dearimgui.com/docs/drawlist_v193
|
||||
bool ConfigDebugDrawListDefaultsToStrokeLegacy; // false // Default all ImDrawList to ImDrawFlags_StrokeLegacy mode, mimicking pre-1.93.0 rendering.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Platform Identifiers
|
||||
// (the imgui_impl_xxxx backend files are setting those up for you)
|
||||
@@ -2761,30 +2791,27 @@ struct ImGuiOnceUponAFrame
|
||||
operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }
|
||||
};
|
||||
|
||||
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
||||
// Helper: Parse and apply text filters e.g. 'aaa bbb' (all), 'aaa,bbb' (any), '-aaa' (exclude), '"Hello, world"' (exact sequence)
|
||||
struct ImGuiTextFilterItem;
|
||||
struct ImGuiTextFilter
|
||||
{
|
||||
IMGUI_API ImGuiTextFilter(const char* default_filter = "");
|
||||
IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
|
||||
IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const;
|
||||
IMGUI_API void Build();
|
||||
void Clear() { InputBuf[0] = 0; Build(); }
|
||||
bool IsActive() const { return !Filters.empty(); }
|
||||
IMGUI_API void Build(); // Update internal data when filter changes
|
||||
inline void Clear() { InputBuf[0] = 0; Build(); } // Clear filter
|
||||
inline bool IsActive() const { return _Items.Size != 0; } // Useful if you need e.g. an alternative code-path when there are no filters
|
||||
|
||||
// [Internal]
|
||||
struct ImGuiTextRange
|
||||
{
|
||||
const char* b;
|
||||
const char* e;
|
||||
// Helper to call InputText() + Build() when buffer is changed.
|
||||
IMGUI_API bool Draw(const char* label = "Filter");
|
||||
IMGUI_API bool DrawWithHint(const char* label = "Filter", const char* hint = "incl -excl");
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); }
|
||||
#endif
|
||||
|
||||
ImGuiTextRange() { b = e = NULL; }
|
||||
ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; }
|
||||
bool empty() const { return b == e; }
|
||||
IMGUI_API void split(char separator, ImVector<ImGuiTextRange>* out) const;
|
||||
};
|
||||
char InputBuf[256];
|
||||
ImVector<ImGuiTextRange>Filters;
|
||||
int CountGrep;
|
||||
// Members
|
||||
char InputBuf[256]; // User input buffer
|
||||
int _CountExclude; // [Internal] >= 0 count of leading exclude
|
||||
ImVector<ImGuiTextFilterItem> _Items; // [Internal] Pre-parsed, trimmed, reordered items
|
||||
};
|
||||
|
||||
// Helper: Growable text buffer for logging/accumulating text
|
||||
@@ -2864,6 +2891,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_
|
||||
{
|
||||
@@ -2937,41 +2978,41 @@ struct ImGuiListClipper
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
// ImVec2 operators
|
||||
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
||||
inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
|
||||
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
||||
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
||||
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
|
||||
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
|
||||
inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
|
||||
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
|
||||
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||
inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
|
||||
inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
||||
inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
|
||||
inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
|
||||
inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
|
||||
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
|
||||
IM_NODEBUGSTEP inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
|
||||
IM_NODEBUGSTEP inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
|
||||
// ImVec4 operators
|
||||
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
|
||||
inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
|
||||
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
|
||||
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
|
||||
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
|
||||
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
|
||||
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
|
||||
inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
|
||||
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
|
||||
inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
|
||||
inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
|
||||
inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
|
||||
inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
|
||||
inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
|
||||
inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
|
||||
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
|
||||
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
|
||||
IM_NODEBUGSTEP inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
|
||||
IM_NODEBUGSTEP inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
|
||||
IM_NODEBUGSTEP inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
#endif
|
||||
|
||||
@@ -3177,15 +3218,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.
|
||||
@@ -3279,40 +3315,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
|
||||
@@ -3330,7 +3408,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.
|
||||
@@ -3343,7 +3421,10 @@ struct ImDrawList
|
||||
ImVector<ImVec4> _ClipRectStack; // [Internal]
|
||||
ImVector<ImTextureRef> _TextureStack; // [Internal]
|
||||
ImVector<ImU8> _CallbacksDataBuf; // [Internal]
|
||||
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().
|
||||
@@ -3356,6 +3437,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); }
|
||||
|
||||
@@ -3366,32 +3449,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
|
||||
@@ -3408,9 +3491,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
|
||||
@@ -3477,6 +3560,7 @@ struct ImDrawList
|
||||
// [Internal helpers]
|
||||
IMGUI_API void _SetDrawListSharedData(ImDrawListSharedData* data);
|
||||
IMGUI_API void _ResetForNewFrame();
|
||||
IMGUI_API void _SetPixelDensity(float pixel_density);
|
||||
IMGUI_API void _ClearFreeMemory();
|
||||
IMGUI_API void _PopUnusedDrawCmd();
|
||||
IMGUI_API void _TryMergeDrawCmds();
|
||||
@@ -3487,6 +3571,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
|
||||
@@ -3704,7 +3795,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:
|
||||
@@ -3742,8 +3834,8 @@ struct ImFontAtlas
|
||||
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
|
||||
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
|
||||
|
||||
// Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts.
|
||||
// - Since 1.92, you can call ClearFonts() mid-frame, if you load new fonts afterwards.
|
||||
// Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts.
|
||||
// - Since 1.92, you can call ClearFonts() mid-frame, if you load new fonts afterwards.
|
||||
// - As we are transitioning toward our new font system the semantic for those functions gets increasingly misleading and are often a source of issues.
|
||||
// TL;DR; most likely, don't use any of those functions. We expect to obsolete/rework them.
|
||||
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
|
||||
@@ -3821,7 +3913,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.
|
||||
@@ -3848,7 +3940,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.
|
||||
@@ -3946,7 +4037,7 @@ struct ImFont
|
||||
ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?')
|
||||
ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 17 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 8K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
|
||||
bool EllipsisAutoBake; // 1 // // Mark when the "..." glyph (== EllipsisChar) needs to be generated by combining multiple '.'.
|
||||
ImGuiStorage RemapPairs; // 16 // // Remapping pairs when using AddRemapChar(), otherwise empty.
|
||||
ImGuiStorage RemapPairs; // 16 // // Remapping pairs when using AddRemapCodepointXXX().
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
float Scale; // 4 // in // Legacy base font scale (~1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
|
||||
#endif
|
||||
@@ -3972,8 +4063,10 @@ struct ImFont
|
||||
|
||||
// [Internal] Don't use!
|
||||
IMGUI_API void ClearOutputData();
|
||||
IMGUI_API void AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint); // Makes 'from_codepoint' character points to 'to_codepoint' glyph.
|
||||
IMGUI_API void AddRemapCodepoint(ImWchar from_codepoint, ImWchar to_codepoint); // Makes 'from_codepoint' character points to 'to_codepoint' glyph.
|
||||
IMGUI_API void AddRemapCodepointToGlyphIndex(ImWchar from_codepoint, int font_src_idx, int glyph_idx);
|
||||
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
|
||||
//inline void AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint) { AddRemapCodepoint(from_codepoint, to_codepoint); } // Renamed in 1.93.0 (Sep 2026)
|
||||
};
|
||||
|
||||
// This is provided for consistency (but we don't actually use this)
|
||||
@@ -4090,6 +4183,7 @@ struct ImGuiPlatformIO
|
||||
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
|
||||
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
|
||||
ImDrawCallback DrawCallback_SetSamplerFromTex; // Request backend to use sampler associated to texture - only available in some backends: OpenGL2/3 and SDLRenderer3.
|
||||
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@@ -4224,6 +4318,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
|
||||
@@ -4247,16 +4353,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)
|
||||
|
||||
+142
-64
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||
@@ -126,7 +126,7 @@ Index of this file:
|
||||
|
||||
// Enable stb_truetype by default unless FreeType is enabled.
|
||||
// You can compile with both by defining both IMGUI_ENABLE_FREETYPE and IMGUI_ENABLE_STB_TRUETYPE together.
|
||||
#ifndef IMGUI_ENABLE_FREETYPE
|
||||
#if !defined(IMGUI_ENABLE_FREETYPE) && !defined(IMGUI_ENABLE_STB_TRUETYPE) && !defined(IMGUI_DISABLE_STB_TRUETYPE)
|
||||
#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
#endif
|
||||
|
||||
@@ -189,6 +189,7 @@ struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aim
|
||||
struct ImGuiWindow; // Storage for one window
|
||||
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
|
||||
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
|
||||
struct ImGuiWindowStackData; // Storage for each window pushed into the stack
|
||||
|
||||
// Enumerations
|
||||
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
|
||||
@@ -284,7 +285,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
|
||||
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
|
||||
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // Positive values only! ImTrunc() is not inlined in MSVC debug builds
|
||||
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only!
|
||||
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only!
|
||||
//#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
|
||||
|
||||
// Hint for branch prediction
|
||||
@@ -367,6 +368,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
// - Helper: ImPool<>
|
||||
// - Helper: ImChunkStream<>
|
||||
// - Helper: ImGuiTextIndex
|
||||
// - Helper: ImGuiTextFilterItem
|
||||
// - Helper: ImGuiStorage
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -406,7 +408,7 @@ IMGUI_API const char* ImStrSkipBlank(const char* str);
|
||||
IMGUI_API int ImStrlenW(const ImWchar* str); // Computer string length (ImWchar string)
|
||||
IMGUI_API const char* ImStrbol(const char* buf_mid_line, const char* buf_begin); // Find beginning-of-line
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; }
|
||||
inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c & ~32 : c; }
|
||||
inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
|
||||
inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
|
||||
inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); }
|
||||
@@ -504,13 +506,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; }
|
||||
@@ -535,8 +547,9 @@ inline ImVec2 ImTrunc(const ImVec2& v) { return
|
||||
inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
||||
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
||||
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
||||
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
|
||||
inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the the bit-hack version (search for "0x1p120f").
|
||||
inline float ImRoundPositive64(float f) { return (float)(ImS64)(f + 0.5f); } // Positive values only.
|
||||
inline float ImRoundSigned64(float f) { return (float)(ImS64)(f >= 0.0f ? f + 0.5f : f - 0.5f); }
|
||||
inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the bit-hack version (search for "0x1p120f").
|
||||
inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||
inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||
@@ -545,12 +558,29 @@ 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
|
||||
IMGUI_API ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t);
|
||||
IMGUI_API ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments
|
||||
IMGUI_API ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol);// For auto-tessellated curves you can use tess_tol = style.CurveTessellationTol
|
||||
IMGUI_API ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments
|
||||
IMGUI_API ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float max_error);// For auto-tessellated curves you can use max_error = style.CurveTessellationMaxError
|
||||
IMGUI_API ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t);
|
||||
IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
|
||||
IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
|
||||
@@ -565,25 +595,25 @@ IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
struct ImVec1
|
||||
{
|
||||
float x;
|
||||
constexpr ImVec1() : x(0.0f) { }
|
||||
constexpr ImVec1(float _x) : x(_x) { }
|
||||
IM_NODEBUGSTEP constexpr inline ImVec1() : x(0.0f) { }
|
||||
IM_NODEBUGSTEP constexpr inline ImVec1(float _x) : x(_x) { }
|
||||
};
|
||||
|
||||
// Helper: ImVec2i (2D vector, integer)
|
||||
struct ImVec2i
|
||||
{
|
||||
int x, y;
|
||||
constexpr ImVec2i() : x(0), y(0) {}
|
||||
constexpr ImVec2i(int _x, int _y) : x(_x), y(_y) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2i() : x(0), y(0) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2i(int _x, int _y) : x(_x), y(_y) {}
|
||||
};
|
||||
|
||||
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
|
||||
struct ImVec2ih
|
||||
{
|
||||
short x, y;
|
||||
constexpr ImVec2ih() : x(0), y(0) {}
|
||||
constexpr ImVec2ih(short _x, short _y) : x(_x), y(_y) {}
|
||||
constexpr explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2ih() : x(0), y(0) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImVec2ih(short _x, short _y) : x(_x), y(_y) {}
|
||||
IM_NODEBUGSTEP constexpr inline explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {}
|
||||
};
|
||||
|
||||
// Helper: ImRect (2D axis aligned bounding-box)
|
||||
@@ -593,10 +623,10 @@ struct IMGUI_API ImRect
|
||||
ImVec2 Min; // Upper-left
|
||||
ImVec2 Max; // Lower-right
|
||||
|
||||
constexpr ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
|
||||
constexpr ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
|
||||
constexpr ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
|
||||
constexpr ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
|
||||
IM_NODEBUGSTEP constexpr inline ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
|
||||
|
||||
ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
|
||||
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
|
||||
@@ -698,13 +728,13 @@ struct ImSpan
|
||||
inline bool empty() const { return Data == DataEnd; }
|
||||
inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
|
||||
inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
|
||||
inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
||||
inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
||||
|
||||
inline T* begin() { return Data; }
|
||||
inline const T* begin() const { return Data; }
|
||||
inline T* end() { return DataEnd; }
|
||||
inline const T* end() const { return DataEnd; }
|
||||
IM_NODEBUGSTEP inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
||||
IM_NODEBUGSTEP inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
||||
IM_NODEBUGSTEP inline T* begin() { return Data; }
|
||||
IM_NODEBUGSTEP inline const T* begin() const { return Data; }
|
||||
IM_NODEBUGSTEP inline T* end() { return DataEnd; }
|
||||
IM_NODEBUGSTEP inline const T* end() const { return DataEnd; }
|
||||
|
||||
// Utilities
|
||||
inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; }
|
||||
@@ -835,6 +865,16 @@ struct ImGuiTextIndex
|
||||
void append(const char* base, int old_size, int new_size);
|
||||
};
|
||||
|
||||
// [Internal] Types
|
||||
struct ImGuiTextFilterItem
|
||||
{
|
||||
const char* Begin; // Pointer within parent's buffer
|
||||
int Len; // Length of text (non-zero terminated)
|
||||
short CountInclude; // Number of consecutive items forming an end chain. >0 when beginning of an AND chain, =0 otherwise.
|
||||
unsigned short MatchIncludesMask; // Storage for multi-sources versions of PassFilter(). Unused by core library.
|
||||
ImGuiTextFilterItem(const char* b, const char* e) { IM_ASSERT(e > b); Begin = b; Len = (int)(e - b); CountInclude = 0; MatchIncludesMask = 0; }
|
||||
};
|
||||
|
||||
// Helper: ImGuiPackedDate (sizeof() == 2)
|
||||
// Store a date in a way that is efficient to read/write in text form. If we stored e.g. number of days since Epoch we'd need costlier back and forth.
|
||||
// This is specifically designed to be able to prune old .ini data.
|
||||
@@ -877,11 +917,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
|
||||
@@ -890,15 +947,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 for simplified AddText overload)
|
||||
float FontSize; // Current font size (used for simplified AddText overload)
|
||||
float FontScale; // Current font scale (== FontSize / Font->FontSize)
|
||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
||||
float CurveTessellationMaxError; // Tessellation tolerance when using PathBezierCurveTo()
|
||||
float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
||||
float InitialFringeScale; // Initial scale to apply to AA fringe
|
||||
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
|
||||
@@ -933,6 +990,8 @@ struct ImFontStackData
|
||||
// [SECTION] Style support
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define ImGuiCol_TextMixedValue ImGuiCol_TextDisabled
|
||||
|
||||
struct ImGuiStyleVarInfo
|
||||
{
|
||||
ImU32 Count : 8; // 1+
|
||||
@@ -994,7 +1053,6 @@ enum ImGuiItemFlagsPrivate_
|
||||
{
|
||||
// Controlled by user
|
||||
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
|
||||
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
|
||||
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
|
||||
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
|
||||
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
|
||||
@@ -1030,7 +1088,7 @@ enum ImGuiItemStatusFlags_
|
||||
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
||||
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
|
||||
ImGuiItemStatusFlags_EditedInternal = 1 << 11, // Similar to ImGuiItemStatusFlags_Edited but bypassing ImGuiItemFlags_NoMarkEdited.
|
||||
|
||||
|
||||
// Additional status + semantic for ImGuiTestEngine
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode)
|
||||
@@ -1084,12 +1142,6 @@ enum ImGuiButtonFlagsPrivate_
|
||||
//ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4
|
||||
};
|
||||
|
||||
// Extend ImGuiComboFlags_
|
||||
enum ImGuiComboFlagsPrivate_
|
||||
{
|
||||
ImGuiComboFlags_CustomPreview = 1 << 20, // enable BeginComboPreview()
|
||||
};
|
||||
|
||||
// Extend ImGuiSliderFlags_
|
||||
enum ImGuiSliderFlagsPrivate_
|
||||
{
|
||||
@@ -1184,6 +1236,10 @@ enum ImGuiPlotType
|
||||
ImGuiPlotType_Histogram,
|
||||
};
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//ImGuiComboFlags_CustomPreview = 1 << 20, // enable BeginComboPreview() // [Obsoleted in 1.93.0] Unnecessary: can now use BeginComboPreview() without a flag.
|
||||
#endif
|
||||
|
||||
// Storage data for BeginComboPreview()/EndComboPreview()
|
||||
struct IMGUI_API ImGuiComboPreviewData
|
||||
{
|
||||
@@ -1192,7 +1248,10 @@ struct IMGUI_API ImGuiComboPreviewData
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
ImVec2 BackupCursorPosPrevLine;
|
||||
float BackupPrevLineTextBaseOffset;
|
||||
ImGuiLayoutType BackupLayout;
|
||||
float BackupWorkRectMaxX;
|
||||
float BackupContentRectMaxX;
|
||||
ImGuiLayoutType BackupLayout : 8;
|
||||
int WithinPreview : 2;
|
||||
|
||||
ImGuiComboPreviewData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
@@ -1281,6 +1340,7 @@ struct IMGUI_API ImGuiInputTextState
|
||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||
bool EditedBefore; // edited since activated
|
||||
bool EditedThisFrame; // edited this frame
|
||||
bool ValidatedThisFrame;
|
||||
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
|
||||
ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s
|
||||
int ReloadSelectionStart;
|
||||
@@ -1361,8 +1421,10 @@ struct ImGuiNextWindowData
|
||||
ImVec2 SizeVal;
|
||||
ImVec2 ContentSizeVal;
|
||||
ImVec2 ScrollVal;
|
||||
ImGuiWindowFlags WindowFlags; // Only honored by BeginTable()
|
||||
ImGuiChildFlags ChildFlags;
|
||||
ImGuiWindowFlags WindowFlagsSet; // Flags to set. Use SetNextWindowFlags()!
|
||||
ImGuiWindowFlags WindowFlagsClear;
|
||||
ImGuiChildFlags ChildFlagsSet; // Flags to set. Use SetNextWindowChildFlags().
|
||||
ImGuiChildFlags ChildFlagsClear;
|
||||
bool CollapsedVal;
|
||||
ImRect SizeConstraintRect;
|
||||
ImGuiSizeCallback SizeCallback;
|
||||
@@ -1456,7 +1518,7 @@ struct IMGUI_API ImGuiErrorRecoveryState
|
||||
ImGuiErrorRecoveryState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Data saved for each window pushed into the stack
|
||||
// Storage for each window pushed into the stack.
|
||||
struct ImGuiWindowStackData
|
||||
{
|
||||
ImGuiWindow* Window;
|
||||
@@ -1464,6 +1526,7 @@ struct ImGuiWindowStackData
|
||||
ImGuiErrorRecoveryState StackSizesInBegin; // Store size of various stacks for asserting
|
||||
bool DisabledOverrideReenable; // Non-child window override disabled flag
|
||||
float DisabledOverrideReenableAlphaBackup;
|
||||
ImRect ParentLastComboPreviewRect;
|
||||
};
|
||||
|
||||
struct ImGuiShrinkWidthItem
|
||||
@@ -1998,8 +2061,9 @@ struct IMGUI_API ImGuiMultiSelectState
|
||||
// Every instance of ImGuiViewport is in fact a ImGuiViewportP.
|
||||
struct ImGuiViewportP : public ImGuiViewport
|
||||
{
|
||||
float BgFgDrawListsLastTimeActive[2]; // Last frame number the background (0) and foreground (1) draw lists were used
|
||||
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
|
||||
int BgFgDrawListsLastFrameActive[2]; // Last frame the background (0) and foreground (1) draw lists were used.
|
||||
float BgFgDrawListsLastTimeActive[2]; // Timestamps for Gc.
|
||||
ImDrawData DrawDataP;
|
||||
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
|
||||
|
||||
@@ -2012,7 +2076,7 @@ struct ImGuiViewportP : public ImGuiViewport
|
||||
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
|
||||
ImVec2 BuildWorkInsetMax; // "
|
||||
|
||||
ImGuiViewportP() { BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0f; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; }
|
||||
ImGuiViewportP() { BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; BgFgDrawListsLastFrameActive[0] = BgFgDrawListsLastFrameActive[1] = -1; BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0; }
|
||||
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
|
||||
|
||||
// Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
|
||||
@@ -2267,7 +2331,7 @@ struct ImGuiContext
|
||||
float FontSize; // Currently bound font size == line height (== FontSizeBase + externals scales applied in the UpdateCurrentFontSize() function).
|
||||
float FontSizeBase; // Font size before scaling == style.FontSizeBase == value passed to PushFont() when specified.
|
||||
float FontBakedScale; // == FontBaked->Size / FontSize. Scale factor over baked size. Rarely used nowadays, very often == 1.0f.
|
||||
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
|
||||
float CurrentPixelDensity; // Current font density. Used by all calls to GetFontBaked().
|
||||
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
||||
ImDrawListSharedData DrawListSharedData;
|
||||
ImGuiID WithinEndChildID; // Set within EndChild()
|
||||
@@ -2303,6 +2367,7 @@ struct ImGuiContext
|
||||
ImVec2 WheelingAxisAvg;
|
||||
|
||||
// Item/widgets state and tracking information
|
||||
const char* MixedValueLabel; // Value replacement when displaying a mixed value. Default to "-" (Unreal uses "Multiple values", Unity uses "---"). May be interpreted as a format: must not contain single %. Set to NULL to display original value.
|
||||
ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier
|
||||
ImGuiID DebugHookIdInfoId; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
|
||||
ImGuiID HoveredId; // Hovered widget, filled during the frame
|
||||
@@ -2437,6 +2502,7 @@ struct ImGuiContext
|
||||
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
|
||||
ImGuiKeyChord NavJustMovedToKeyMods;
|
||||
bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
|
||||
bool NavJustMovedToIsInit; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
|
||||
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
|
||||
|
||||
// Navigation: extra config options (will be made public eventually)
|
||||
@@ -2690,7 +2756,7 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
|
||||
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
|
||||
int TreeDepth; // Current tree depth.
|
||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. Sync any changes with TREE_NODE_MAX_DEPTH/TREE_NODE_GET_DEPTH_MASK!
|
||||
ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set.
|
||||
ImVector<ImGuiWindow*> ChildWindows;
|
||||
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
|
||||
@@ -3117,9 +3183,9 @@ struct IMGUI_API ImGuiTable
|
||||
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
|
||||
ImGuiTableInstanceData InstanceDataFirst;
|
||||
ImVector<ImGuiTableInstanceData> InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImGuiTableColumnIdx SortSpecsCount;
|
||||
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
|
||||
ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns using fixed width (<= ColumnsCount)
|
||||
@@ -3151,6 +3217,7 @@ struct IMGUI_API ImGuiTable
|
||||
ImS8 NavLayer; // ImGuiNavLayer at the time of BeginTable().
|
||||
bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row.
|
||||
bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
|
||||
bool IsNewTable;
|
||||
bool IsInitializing;
|
||||
bool IsReconcileMode;
|
||||
bool IsSortSpecsDirty;
|
||||
@@ -3252,7 +3319,7 @@ struct ImGuiTableSettings
|
||||
};
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
{
|
||||
// Tables: Candidates for public API
|
||||
IMGUI_API void TableOpenContextMenu(int column_n = -1);
|
||||
IMGUI_API void TableSetColumnWidth(int column_n, float width);
|
||||
@@ -3346,7 +3413,7 @@ namespace ImGui
|
||||
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||
IMGUI_API ImGuiIO& GetIO(ImGuiContext* ctx);
|
||||
IMGUI_API ImGuiPlatformIO& GetPlatformIO(ImGuiContext* ctx);
|
||||
inline float GetScale() { ImGuiContext& g = *GImGui; return g.Style._MainScale; } // FIXME-DPI: I don't want to formalize this just yet. Because reasons. Please don't use.
|
||||
inline float GetScale() { ImGuiContext& g = *GImGui; return g.Style._MainScale; } // FIXME-DPI: PLEASE DO NOT USE. I don't want to formalize this just yet. Because reasons.
|
||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
|
||||
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
||||
@@ -3369,6 +3436,8 @@ namespace ImGui
|
||||
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
|
||||
inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.y - off.y); }
|
||||
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
|
||||
IMGUI_API void SetNextWindowFlags(ImGuiWindowFlags flags, bool enabled);
|
||||
IMGUI_API void SetNextWindowChildFlags(ImGuiChildFlags flags, bool enabled);
|
||||
|
||||
// Windows: Display Order and Focus Order
|
||||
IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0);
|
||||
@@ -3390,8 +3459,8 @@ namespace ImGui
|
||||
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling);
|
||||
IMGUI_API void UpdateCurrentFontSize(float restore_font_size_after_scaling);
|
||||
IMGUI_API void SetFontRasterizerDensity(float rasterizer_density);
|
||||
inline float GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
|
||||
IMGUI_API void SetPixelDensity(float pixel_density); // was SetFontRasterizerDensity()
|
||||
inline float GetPixelDensity() { return GImGui->CurrentPixelDensity; }
|
||||
inline float GetRoundedFontSize(float size) { return IM_ROUND(size); }
|
||||
IMGUI_API ImFont* GetDefaultFont();
|
||||
IMGUI_API void PushPasswordFont();
|
||||
@@ -3531,7 +3600,7 @@ namespace ImGui
|
||||
|
||||
// Combos
|
||||
IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);
|
||||
IMGUI_API bool BeginComboPreview();
|
||||
IMGUI_API bool BeginComboPreview(); // Submit preview contents a combo. Call this after EndCombo() to display contents that's more than just a text label.
|
||||
IMGUI_API void EndComboPreview();
|
||||
|
||||
// Keyboard/Gamepad Navigation
|
||||
@@ -3664,6 +3733,7 @@ namespace ImGui
|
||||
IMGUI_API void ClearDragDrop();
|
||||
IMGUI_API bool IsDragDropPayloadBeingAccepted();
|
||||
IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectForViewport(ImGuiID viewport_id, const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding);
|
||||
|
||||
// Typing-Select API
|
||||
@@ -3696,6 +3766,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar);
|
||||
inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); }
|
||||
IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
IMGUI_API ImVec2 TabBarGetTabPos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
|
||||
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
IMGUI_API void TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
@@ -3721,7 +3792,7 @@ namespace ImGui
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float alpha, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None, float rounding = -1.0f); // Navigation highlight
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
|
||||
@@ -3740,8 +3811,8 @@ namespace ImGui
|
||||
|
||||
// Widgets: Text
|
||||
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
|
||||
IMGUI_API void TextAligned(float align_x, float size_x, const char* fmt, ...); // FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||
IMGUI_API void TextAlignedV(float align_x, float size_x, const char* fmt, va_list args);
|
||||
IMGUI_API void TextAligned(float align_x, float width, const char* fmt, ...) IM_FMTARGS(3); // FIXME-WIP: Works but API is likely to be reworked.
|
||||
IMGUI_API void TextAlignedV(float align_x, float width, const char* fmt, va_list args) IM_FMTLIST(3);
|
||||
|
||||
// Widgets
|
||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
@@ -3906,10 +3977,11 @@ struct ImFontLoader
|
||||
void (*LoaderShutdown)(ImFontAtlas* atlas);
|
||||
bool (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
void (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
|
||||
int (*FontSrcGetGlyphIndexFromCodepoint)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint); // Required
|
||||
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, int glyph_index);
|
||||
bool (*FontBakedInit)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||
void (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x);
|
||||
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x); // Required
|
||||
|
||||
// Size of backend data, Per Baked * Per Source. Buffers are managed by core to avoid excessive allocations.
|
||||
// FIXME: At this point the two other types of buffers may be managed by core to be consistent?
|
||||
@@ -4011,8 +4083,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);
|
||||
|
||||
Vendored
+278
-152
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (main code and documentation)
|
||||
|
||||
// Help:
|
||||
@@ -230,7 +230,7 @@ CODE
|
||||
This is to increase compatibility, increase maintainability and facilitate use from other languages.
|
||||
- C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
|
||||
See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
|
||||
We can can optionally export math operators for ImVec2/ImVec4 using IMGUI_DEFINE_MATH_OPERATORS, which we use internally.
|
||||
We can optionally export math operators for ImVec2/ImVec4 using IMGUI_DEFINE_MATH_OPERATORS, which we use internally.
|
||||
- C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction
|
||||
(so don't use ImVector in your code or at our own risk!).
|
||||
- Building: We don't use nor mandate a build system for the main library.
|
||||
@@ -395,6 +395,51 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
||||
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||
|
||||
2026/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 ImDrawFlags_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.
|
||||
- style.CurveTessellationMaxError == sqrtf(style.CurveTessellationTol).
|
||||
- 2026/07/20 (1.92.9) - DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now defaulting to being disabled:
|
||||
inputting a value with the keyboard doesn't write intermediate values to backing variable. (#9476)
|
||||
- Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123.
|
||||
@@ -1385,10 +1430,9 @@ static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti
|
||||
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
|
||||
|
||||
// Platform Dependents default implementation for ImGuiPlatformIO functions
|
||||
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io);
|
||||
static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx);
|
||||
static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text);
|
||||
static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data);
|
||||
static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path);
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
@@ -1570,10 +1614,12 @@ ImGuiStyle::ImGuiStyle()
|
||||
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
|
||||
DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
|
||||
MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
|
||||
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.).
|
||||
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
|
||||
|
||||
// Rendering & Tessellation
|
||||
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.
|
||||
|
||||
// Behaviors
|
||||
@@ -1586,6 +1632,10 @@ ImGuiStyle::ImGuiStyle()
|
||||
// [Internal]
|
||||
_MainScale = 1.0f;
|
||||
_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
|
||||
ImGui::StyleColorsDark(this);
|
||||
@@ -2100,7 +2150,7 @@ ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec
|
||||
}
|
||||
|
||||
// Closely mimics PathBezierToCasteljau() in imgui_draw.cpp
|
||||
static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
|
||||
static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float max_error_sqr, int level)
|
||||
{
|
||||
float dx = x4 - x1;
|
||||
float dy = y4 - y1;
|
||||
@@ -2108,7 +2158,7 @@ static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_cl
|
||||
float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
|
||||
d2 = (d2 >= 0) ? d2 : -d2;
|
||||
d3 = (d3 >= 0) ? d3 : -d3;
|
||||
if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
|
||||
if ((d2 + d3) * (d2 + d3) < max_error_sqr * (dx * dx + dy * dy))
|
||||
{
|
||||
ImVec2 p_current(x4, y4);
|
||||
ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
|
||||
@@ -2128,20 +2178,21 @@ static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_cl
|
||||
float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
|
||||
float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
|
||||
float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, max_error_sqr, level + 1);
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, max_error_sqr, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol
|
||||
// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationMaxError
|
||||
// Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically.
|
||||
ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol)
|
||||
ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float max_error)
|
||||
{
|
||||
IM_ASSERT(tess_tol > 0.0f);
|
||||
IM_ASSERT(max_error > 0.0f);
|
||||
ImVec2 p_last = p1;
|
||||
ImVec2 p_closest;
|
||||
float p_closest_dist2 = FLT_MAX;
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0);
|
||||
float max_error_sqr = max_error * max_error;
|
||||
ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, max_error_sqr, 0);
|
||||
return p_closest;
|
||||
}
|
||||
|
||||
@@ -2485,7 +2536,13 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed)
|
||||
#else
|
||||
while (data + 4 <= data_end)
|
||||
{
|
||||
#if defined(_DEBUG) || defined(_MSC_VER)
|
||||
crc = _mm_crc32_u32(crc, *(ImU32*)data);
|
||||
#else
|
||||
ImU32 v;
|
||||
memcpy(&v, data, sizeof(ImU32)); // Avoid aliasing violation (#9557)
|
||||
crc = _mm_crc32_u32(crc, v);
|
||||
#endif
|
||||
data += 4;
|
||||
}
|
||||
while (data < data_end)
|
||||
@@ -3082,11 +3139,11 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
// [SECTION] ImGuiTextFilter
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
||||
// Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'.
|
||||
ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
|
||||
{
|
||||
InputBuf[0] = 0;
|
||||
CountGrep = 0;
|
||||
_CountExclude = 0;
|
||||
if (default_filter)
|
||||
{
|
||||
ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf));
|
||||
@@ -3094,84 +3151,110 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiTextFilter::Draw(const char* label, float width)
|
||||
bool ImGuiTextFilter::Draw(const char* label)
|
||||
{
|
||||
if (width != 0.0f)
|
||||
ImGui::SetNextItemWidth(width);
|
||||
bool value_changed = ImGui::InputText(label, InputBuf, IM_COUNTOF(InputBuf));
|
||||
return DrawWithHint(label, "incl -excl");
|
||||
}
|
||||
|
||||
// Use ImGui::SetNextItemWidth() manually if you want to use this.
|
||||
bool ImGuiTextFilter::DrawWithHint(const char* label, const char* hint)
|
||||
{
|
||||
bool value_changed = ImGui::InputTextWithHint(label, hint, InputBuf, IM_COUNTOF(InputBuf));
|
||||
if (value_changed)
|
||||
Build();
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRange>* out) const
|
||||
{
|
||||
out->resize(0);
|
||||
const char* wb = b;
|
||||
const char* we = wb;
|
||||
while (we < e)
|
||||
{
|
||||
if (*we == separator)
|
||||
{
|
||||
out->push_back(ImGuiTextRange(wb, we));
|
||||
wb = we + 1;
|
||||
}
|
||||
we++;
|
||||
}
|
||||
if (wb != we)
|
||||
out->push_back(ImGuiTextRange(wb, we));
|
||||
}
|
||||
|
||||
// Parse filter and split into a format optimal for PassFilter()
|
||||
void ImGuiTextFilter::Build()
|
||||
{
|
||||
Filters.resize(0);
|
||||
ImGuiTextRange input_range(InputBuf, InputBuf + ImStrlen(InputBuf));
|
||||
input_range.split(',', &Filters);
|
||||
_Items.resize(0);
|
||||
_CountExclude = 0;
|
||||
|
||||
CountGrep = 0;
|
||||
for (ImGuiTextRange& f : Filters)
|
||||
const char* buf_e = InputBuf + ImStrlen(InputBuf);
|
||||
const char* word_e;
|
||||
int seq_start_idx = -1;
|
||||
for (const char* word_b = InputBuf; word_b < buf_e; word_b = word_e + 1)
|
||||
{
|
||||
while (f.b < f.e && ImCharIsBlankA(f.b[0]))
|
||||
f.b++;
|
||||
while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
|
||||
f.e--;
|
||||
if (f.empty())
|
||||
continue;
|
||||
if (f.b[0] != '-')
|
||||
CountGrep += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
|
||||
{
|
||||
if (Filters.Size == 0)
|
||||
return true;
|
||||
|
||||
if (text == NULL)
|
||||
text = text_end = "";
|
||||
|
||||
for (const ImGuiTextRange& f : Filters)
|
||||
{
|
||||
if (f.b == f.e)
|
||||
continue;
|
||||
if (f.b[0] == '-')
|
||||
// Trim blanks
|
||||
while (word_b < buf_e && ImCharIsBlankA(word_b[0])) // FIXME: UTF-8 support
|
||||
word_b++;
|
||||
const bool is_excl = (word_b < buf_e && word_b[0] == '-');
|
||||
if (is_excl)
|
||||
word_b++;
|
||||
const bool is_quote = (word_b < buf_e && word_b[0] == '\"');
|
||||
if (is_quote)
|
||||
{
|
||||
// Subtract
|
||||
if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
|
||||
return false;
|
||||
// Parsing quotes. Omit storing leading/trailing quotes.
|
||||
word_e = ImStrchrRange(++word_b, buf_e, '\"');
|
||||
if (word_e == NULL)
|
||||
word_e = buf_e;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grep
|
||||
if (ImStristr(text, text_end, f.b, f.e) != NULL)
|
||||
return true;
|
||||
// Handle both ' ' and ',' separators.
|
||||
for (word_e = word_b; word_e < buf_e; word_e++)
|
||||
if (*word_e == ' ' || *word_e == ',')
|
||||
break;
|
||||
}
|
||||
|
||||
// Min length
|
||||
if (word_e - word_b > 0)
|
||||
{
|
||||
// Add to list. The '-' is not stored in items but implicitly inferred using (n < CountExclude).
|
||||
// FIXME-OPT: as items are derived from user input buffer and we expect the insert() to behave sanely.
|
||||
if (is_excl)
|
||||
{
|
||||
_Items.insert(_Items.Data + _CountExclude, ImGuiTextFilterItem(word_b, word_e));
|
||||
_CountExclude++;
|
||||
if (seq_start_idx != -1)
|
||||
seq_start_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seq_start_idx == -1)
|
||||
seq_start_idx = _Items.Size;
|
||||
_Items.insert(_Items.Data + _Items.Size, ImGuiTextFilterItem(word_b, word_e));
|
||||
_Items.Data[seq_start_idx].CountInclude++;
|
||||
}
|
||||
}
|
||||
|
||||
// Next sequence
|
||||
if (word_e[0] == ',')
|
||||
seq_start_idx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Implicit * grep
|
||||
if (CountGrep == 0)
|
||||
// FIXME: Could use a specialized ImStristr() + pre-convert our filter to uppercase.
|
||||
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
|
||||
{
|
||||
if (_Items.Size == 0)
|
||||
return true;
|
||||
if (text == NULL)
|
||||
text = text_end = "";
|
||||
|
||||
// Filters are sorted so that '-' ones are always leading.
|
||||
ImGuiTextFilterItem* seq = _Items.Data;
|
||||
ImGuiTextFilterItem* seq_excl_end = _Items.Data + _CountExclude;
|
||||
for (; seq < seq_excl_end; seq++)
|
||||
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) != NULL)
|
||||
return false;
|
||||
|
||||
// Process includes
|
||||
ImGuiTextFilterItem* seq_end = _Items.Data + _Items.Size;
|
||||
if (seq == seq_end) // When no inclusion are specified (only exclusions) we implicitly pass
|
||||
return true;
|
||||
while (seq < seq_end)
|
||||
{
|
||||
ImGuiTextFilterItem* seq_incl_end = seq + seq->CountInclude;
|
||||
IM_ASSERT_PARANOID(seq->CountInclude > 0 && seq_incl_end <= seq_end);
|
||||
for (; seq < seq_incl_end; seq++)
|
||||
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) == NULL)
|
||||
break;
|
||||
if (seq == seq_incl_end) // All matched
|
||||
return true;
|
||||
seq = seq_incl_end; // Try next
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3938,6 +4021,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
||||
// Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take
|
||||
// better advantage of the render function taking size into account for coarse clipping.
|
||||
void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
|
||||
// DOES NOT CALL LogRenderedText(), unlike RenderTextClipped!!!
|
||||
{
|
||||
// Perform CPU side clipping for single clipped element to avoid using scissor state
|
||||
ImVec2 pos = pos_min;
|
||||
@@ -4232,7 +4316,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
Font = NULL;
|
||||
FontBaked = NULL;
|
||||
FontSize = FontSizeBase = FontBakedScale = CurrentDpiScale = 0.0f;
|
||||
FontRasterizerDensity = 1.0f;
|
||||
CurrentPixelDensity = 1.0f;
|
||||
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
|
||||
if (shared_font_atlas == NULL)
|
||||
IO.Fonts->OwnerContext = this;
|
||||
@@ -4329,7 +4413,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
|
||||
NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
|
||||
NavJustMovedToKeyMods = ImGuiMod_None;
|
||||
NavJustMovedToIsTabbing = false;
|
||||
NavJustMovedToIsTabbing = NavJustMovedToIsInit = false;
|
||||
NavJustMovedToHasSelectionData = false;
|
||||
|
||||
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
|
||||
@@ -4373,6 +4457,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
MouseStationaryTimer = 0.0f;
|
||||
|
||||
MixedValueLabel = "-";
|
||||
InputTextPasswordFontBackupFlags = ImFontFlags_None;
|
||||
InputTextReactivateId = 0;
|
||||
TempInputId = 0;
|
||||
@@ -4478,10 +4563,7 @@ void ImGui::Initialize()
|
||||
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_COUNTOF(GLocalizationEntriesEnUS));
|
||||
|
||||
// Setup default ImGuiPlatformIO clipboard/IME handlers.
|
||||
g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
|
||||
g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
|
||||
g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
|
||||
g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
|
||||
InitializeDefaultPlatformHandlers(g.PlatformIO);
|
||||
|
||||
// Setup session starting date
|
||||
#ifndef IMGUI_DISABLE_TIME_FUNCTIONS
|
||||
@@ -4703,7 +4785,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
|
||||
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
|
||||
{
|
||||
ImGuiViewport* viewport = window->Viewport;
|
||||
g.FontRasterizerDensity = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale.x : g.IO.DisplayFramebufferScale.x; // == SetFontRasterizerDensity()
|
||||
g.CurrentPixelDensity = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale.x : g.IO.DisplayFramebufferScale.x; // == SetPixelDensity()
|
||||
}
|
||||
const bool backup_skip_items = window->SkipItems;
|
||||
window->SkipItems = false;
|
||||
@@ -5297,11 +5379,13 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
|
||||
}
|
||||
|
||||
// Our ImDrawList system requires that there is always a command
|
||||
if (viewport->BgFgDrawListsLastTimeActive[drawlist_no] != (float)g.Time)
|
||||
if (viewport->BgFgDrawListsLastFrameActive[drawlist_no] != g.FrameCount)
|
||||
{
|
||||
draw_list->_ResetForNewFrame();
|
||||
draw_list->_SetPixelDensity(viewport->FramebufferScale.x);
|
||||
draw_list->PushTexture(g.IO.Fonts->TexRef);
|
||||
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
|
||||
viewport->BgFgDrawListsLastFrameActive[drawlist_no] = g.FrameCount;
|
||||
viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time;
|
||||
}
|
||||
return draw_list;
|
||||
@@ -5572,18 +5656,23 @@ static void SetupDrawListSharedData()
|
||||
for (ImGuiViewportP* viewport : g.Viewports)
|
||||
virtual_space.Add(viewport->GetMainRect());
|
||||
g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
|
||||
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
|
||||
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.InitialFringeScale = 1.0f; // FIXME-DPI: Change this for some DPI scaling experiments.
|
||||
g.DrawListSharedData.InitialDrawFlags |= ImDrawFlags_UseVtxOffset;
|
||||
}
|
||||
|
||||
void ImGui::NewFrame()
|
||||
@@ -6204,7 +6293,7 @@ void ImGui::Render()
|
||||
for (ImGuiViewportP* viewport : g.Viewports)
|
||||
{
|
||||
InitViewportDrawData(viewport);
|
||||
if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastTimeActive[0] == (float)g.Time)
|
||||
if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastFrameActive[0] == g.FrameCount)
|
||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
|
||||
}
|
||||
|
||||
@@ -6236,7 +6325,7 @@ void ImGui::Render()
|
||||
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
|
||||
|
||||
// Add foreground ImDrawList (for each active viewport)
|
||||
if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastTimeActive[1] == (float)g.Time)
|
||||
if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastFrameActive[1] == g.FrameCount)
|
||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
|
||||
|
||||
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
|
||||
@@ -6529,6 +6618,9 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
||||
ImGuiWindow* parent_window = g.CurrentWindow;
|
||||
IM_ASSERT(id != 0);
|
||||
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
|
||||
child_flags = (child_flags | g.NextWindowData.ChildFlagsSet) & ~g.NextWindowData.ChildFlagsClear;
|
||||
|
||||
// Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument.
|
||||
const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened;
|
||||
IM_UNUSED(ImGuiChildFlags_SupportedMask_);
|
||||
@@ -6591,13 +6683,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
||||
}
|
||||
}
|
||||
SetNextWindowSize(size);
|
||||
|
||||
// Forward child flags (we allow prior settings to merge but it'll only work for adding flags)
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
|
||||
g.NextWindowData.ChildFlags |= child_flags;
|
||||
else
|
||||
g.NextWindowData.ChildFlags = child_flags;
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
SetNextWindowChildFlags(child_flags, true);
|
||||
|
||||
// Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
|
||||
// FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround.
|
||||
@@ -7267,7 +7353,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
||||
{
|
||||
float y = window->Pos.y + window->TitleBarHeight - 1;
|
||||
window->DrawList->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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7315,7 +7401,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
if (bg_col & IM_COL32_A_MASK)
|
||||
{
|
||||
ImRect bg_rect(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size);
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersBottom;
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundAll : ImDrawFlags_RoundBottom;
|
||||
ImDrawList* bg_draw_list = window->DrawList;
|
||||
bg_draw_list->AddRectFilled(bg_rect.Min, bg_rect.Max, bg_col, window_rounding, bg_rounding_flags);
|
||||
}
|
||||
@@ -7325,7 +7411,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
if (!(flags & ImGuiWindowFlags_NoTitleBar))
|
||||
{
|
||||
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
|
||||
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
|
||||
@@ -7333,9 +7419,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);
|
||||
}
|
||||
|
||||
// Scrollbars
|
||||
@@ -7542,6 +7628,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
if (g.DebugBreakInWindow == window->ID)
|
||||
IM_DEBUG_BREAK();
|
||||
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags)
|
||||
flags = (flags | g.NextWindowData.WindowFlagsSet) & ~g.NextWindowData.WindowFlagsClear;
|
||||
|
||||
// Automatically disable manual moving/resizing when NoInputs is set
|
||||
if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
|
||||
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||
@@ -7567,7 +7656,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
{
|
||||
UpdateWindowInFocusOrderList(window, window_just_created, flags);
|
||||
window->Flags = (ImGuiWindowFlags)flags;
|
||||
window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0;
|
||||
window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlagsSet : 0;
|
||||
window->LastFrameActive = current_frame;
|
||||
window->LastTimeActive = (float)g.Time;
|
||||
window->BeginOrderWithinParent = 0;
|
||||
@@ -7721,6 +7810,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
size_t buf_len = (size_t)window->NameBufLen;
|
||||
window->Name = ImStrdupcpy(window->Name, &buf_len, name);
|
||||
window->NameBufLen = (int)buf_len;
|
||||
window->DrawList->_OwnerName = window->Name;
|
||||
}
|
||||
|
||||
// UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
|
||||
@@ -8073,6 +8163,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
|
||||
// Setup draw list and outer clipping rectangle
|
||||
IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
|
||||
window->DrawList->_SetPixelDensity(window->Viewport->FramebufferScale.x);
|
||||
window->DrawList->PushTexture(g.Font->OwnerAtlas->TexRef);
|
||||
PushClipRect(host_rect.Min, host_rect.Max, false);
|
||||
|
||||
@@ -8219,7 +8310,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// Set default BgClickFlags
|
||||
// This is set at the end of this function, so UpdateWindowManualResize()/ClampWindowPos() may use last-frame value if overridden by user code.
|
||||
// FIXME: The general intent is that we will later expose config options to default to enable scrolling + select scrolling mouse button.
|
||||
window->BgClickFlags = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->BgClickFlags : (g.IO.ConfigWindowsMoveFromTitleBarOnly ? ImGuiWindowBgClickFlags_None : ImGuiWindowBgClickFlags_Move);
|
||||
window->BgClickFlags = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->BgClickFlags : (g.IO.ConfigWindowsMoveFromTitleBarOnly ? ImGuiWindowBgClickFlags_None : ImGuiWindowBgClickFlags_Move); // -V1004
|
||||
|
||||
// We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
|
||||
// This is useful to allow creating context menus on title bar only, etc.
|
||||
@@ -8825,6 +8916,26 @@ void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags)
|
||||
g.NextWindowData.RefreshFlagsVal = flags;
|
||||
}
|
||||
|
||||
void ImGui::SetNextWindowFlags(ImGuiWindowFlags flags, bool enabled)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) == 0)
|
||||
g.NextWindowData.WindowFlagsSet = g.NextWindowData.WindowFlagsClear = ImGuiChildFlags_None;
|
||||
g.NextWindowData.WindowFlagsSet = enabled ? (g.NextWindowData.WindowFlagsSet | flags) : (g.NextWindowData.WindowFlagsSet & ~flags);
|
||||
g.NextWindowData.WindowFlagsClear = !enabled ? (g.NextWindowData.WindowFlagsClear | flags) : (g.NextWindowData.WindowFlagsClear & ~flags);
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasWindowFlags;
|
||||
}
|
||||
|
||||
void ImGui::SetNextWindowChildFlags(ImGuiChildFlags flags, bool enabled)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) == 0)
|
||||
g.NextWindowData.ChildFlagsSet = g.NextWindowData.ChildFlagsClear = ImGuiChildFlags_None;
|
||||
g.NextWindowData.ChildFlagsSet = enabled ? (g.NextWindowData.ChildFlagsSet | flags) : (g.NextWindowData.ChildFlagsSet & ~flags);
|
||||
g.NextWindowData.ChildFlagsClear = !enabled ? (g.NextWindowData.ChildFlagsClear | flags) : (g.NextWindowData.ChildFlagsClear & ~flags);
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
}
|
||||
|
||||
ImDrawList* ImGui::GetWindowDrawList()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -9041,7 +9152,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
|
||||
// - UnregisterFontAtlas() [Internal]
|
||||
// - SetCurrentFont() [Internal]
|
||||
// - UpdateCurrentFontSize() [Internal]
|
||||
// - SetFontRasterizerDensity() [Internal]
|
||||
// - SetPixelDensity() [Internal]
|
||||
// - PushFont()
|
||||
// - PopFont()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -9234,7 +9345,7 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
|
||||
final_size = GetRoundedFontSize(final_size);
|
||||
final_size = ImClamp(final_size, 1.0f, IMGUI_FONT_SIZE_MAX);
|
||||
if (g.Font != NULL && (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures))
|
||||
g.Font->CurrentRasterizerDensity = g.FontRasterizerDensity;
|
||||
g.Font->CurrentRasterizerDensity = g.CurrentPixelDensity;
|
||||
|
||||
g.FontSize = final_size;
|
||||
g.DrawListSharedData.FontSize = g.FontSize;
|
||||
@@ -9258,13 +9369,13 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
|
||||
|
||||
// Exposed in case user may want to override setting density.
|
||||
// IMPORTANT: Begin()/End() is overriding density. Be considerate of this you change it.
|
||||
void ImGui::SetFontRasterizerDensity(float rasterizer_density)
|
||||
void ImGui::SetPixelDensity(float pixel_density)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures);
|
||||
if (g.FontRasterizerDensity == rasterizer_density)
|
||||
if (g.CurrentPixelDensity == pixel_density)
|
||||
return;
|
||||
g.FontRasterizerDensity = rasterizer_density;
|
||||
g.CurrentPixelDensity = pixel_density;
|
||||
UpdateCurrentFontSize(0.0f);
|
||||
}
|
||||
|
||||
@@ -10214,12 +10325,11 @@ void ImGui::TeleportMousePos(const ImVec2& pos)
|
||||
//IMGUI_DEBUG_LOG_IO("TeleportMousePos: (%.1f,%.1f)\n", io.MousePos.x, io.MousePos.y);
|
||||
}
|
||||
|
||||
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
|
||||
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.BeginPopupStack.Size > 0)
|
||||
return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
|
||||
return g.BeginPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
|
||||
return g.IO.MousePos;
|
||||
}
|
||||
|
||||
@@ -11098,7 +11208,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!");
|
||||
IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
|
||||
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!");
|
||||
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
|
||||
IM_ASSERT(g.Style.CurveTessellationMaxError > 0.0f && "Invalid style setting!");
|
||||
IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
|
||||
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
|
||||
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting!");
|
||||
@@ -11138,6 +11248,11 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
g.PlatformIO.Platform_GetClipboardTextFn = [](ImGuiContext* ctx) { return ctx->IO.GetClipboardTextFn(ctx->IO.ClipboardUserData); };
|
||||
if (g.IO.SetClipboardTextFn != NULL && (g.PlatformIO.Platform_SetClipboardTextFn == NULL || g.PlatformIO.Platform_SetClipboardTextFn == Platform_SetClipboardTextFn_DefaultImpl))
|
||||
g.PlatformIO.Platform_SetClipboardTextFn = [](ImGuiContext* ctx, const char* text) { return ctx->IO.SetClipboardTextFn(ctx->IO.ClipboardUserData, text); };
|
||||
|
||||
// Remap legacy CurveTessellationTol into CurveTessellationMaxError (OBSOLETED in 1.93.0, August 2026)
|
||||
if (g.Style.CurveTessellationTol != 0.0f)
|
||||
g.Style.CurveTessellationMaxError = ImSqrt(g.Style.CurveTessellationTol);
|
||||
g.Style.CurveTessellationTol = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -12020,7 +12135,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
|
||||
}
|
||||
scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
|
||||
}
|
||||
scroll[axis] = ImRound64(ImMax(scroll[axis], 0.0f));
|
||||
scroll[axis] = ImRoundPositive64(ImMax(scroll[axis], 0.0f));
|
||||
if (!window->Collapsed && !window->SkipItems)
|
||||
scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
|
||||
}
|
||||
@@ -12660,13 +12775,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext
|
||||
// As we bypass BeginChild(), set ImGuiChildFlags_AlwaysAutoResize as it is checked independently from ImGuiWindowFlags_AlwaysAutoResize for now (see #9355)
|
||||
// Ideally we should remove setting ImGuiWindowFlags_AlwaysAutoResize in BeginChild().
|
||||
if ((extra_window_flags & ImGuiWindowFlags_ChildWindow) && (extra_window_flags & ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
|
||||
g.NextWindowData.ChildFlags |= ImGuiChildFlags_AlwaysAutoResize;
|
||||
else
|
||||
g.NextWindowData.ChildFlags = ImGuiChildFlags_AlwaysAutoResize;
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
}
|
||||
SetNextWindowChildFlags(ImGuiChildFlags_AlwaysAutoResize, true);
|
||||
|
||||
char name[128];
|
||||
IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
|
||||
@@ -12767,7 +12876,7 @@ bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
||||
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||
if (IsMouseReleased(mouse_button, id) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||
return true;
|
||||
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
|
||||
return true;
|
||||
@@ -12778,7 +12887,7 @@ bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
||||
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||
if (IsMouseReleased(mouse_button, ImGuiKeyOwner_NoOwner) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
|
||||
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
|
||||
return true;
|
||||
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
|
||||
@@ -12805,7 +12914,7 @@ bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags
|
||||
// This is a helper to handle the simplest case of associating one named popup to one given widget.
|
||||
// - To create a popup associated to the last item, you generally want to pass a NULL value to str_id.
|
||||
// - To create a popup with a specific identifier, pass it in str_id.
|
||||
// - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call.
|
||||
// - This is useful when using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call.
|
||||
// - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id.
|
||||
// - You may want to handle the whole on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
|
||||
// This is essentially the same as:
|
||||
@@ -12849,9 +12958,9 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flag
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (!str_id)
|
||||
str_id = "void_context";
|
||||
ImGuiID id = window->GetID(str_id);
|
||||
ImGuiID id = window->GetID(str_id); // FIXME: Use a global ID?
|
||||
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
|
||||
if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
|
||||
if (IsMouseReleased(mouse_button, id) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
|
||||
if (GetTopMostPopupModal() == NULL)
|
||||
OpenPopupEx(id, popup_flags);
|
||||
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
|
||||
@@ -14147,6 +14256,7 @@ void ImGui::NavInitRequestApplyResult()
|
||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||
g.NavJustMovedToKeyMods = 0;
|
||||
g.NavJustMovedToIsTabbing = false;
|
||||
g.NavJustMovedToIsInit = true;
|
||||
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
|
||||
}
|
||||
|
||||
@@ -14414,6 +14524,7 @@ void ImGui::NavMoveRequestApplyResult()
|
||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
|
||||
g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
|
||||
g.NavJustMovedToIsInit = false;
|
||||
g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
|
||||
//IMGUI_DEBUG_LOG_NAV("[nav] NavJustMovedFromFocusScopeId = 0x%08X, NavJustMovedToFocusScopeId = 0x%08X\n", g.NavJustMovedFromFocusScopeId, g.NavJustMovedToFocusScopeId);
|
||||
}
|
||||
@@ -15330,15 +15441,9 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
|
||||
flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that live for 1 frame)
|
||||
const bool draw_target_rect = payload.Preview && !(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
|
||||
if (draw_target_rect && g.DragDropTargetFullViewport != 0)
|
||||
{
|
||||
ImRect bb = g.DragDropTargetRect;
|
||||
bb.Expand(-3.5f);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb, g.Style.DragDropTargetRounding);
|
||||
}
|
||||
RenderDragDropTargetRectForViewport(g.DragDropTargetFullViewport, g.DragDropTargetRect);
|
||||
else if (draw_target_rect)
|
||||
{
|
||||
RenderDragDropTargetRectForItem(r);
|
||||
}
|
||||
|
||||
g.DragDropAcceptFrameCount = g.FrameCount;
|
||||
if ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) && g.DragDropMouseButton == -1)
|
||||
@@ -15369,6 +15474,17 @@ void ImGui::RenderDragDropTargetRectForItem(const ImRect& bb)
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
|
||||
void ImGui::RenderDragDropTargetRectForViewport(ImGuiID viewport_id, const ImRect& bb)
|
||||
{
|
||||
IM_ASSERT(viewport_id != 0);
|
||||
IM_UNUSED(viewport_id); // Unused in this branch
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiViewport* viewport = g.Viewports[0];
|
||||
ImRect bb_padded = bb;
|
||||
bb_padded.Expand(-g.Style.DragDropTargetPadding);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(viewport), bb_padded, g.Style.DragDropTargetRounding);
|
||||
}
|
||||
|
||||
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -16072,13 +16188,14 @@ void ImGuiPlatformIO::ClearPlatformHandlers()
|
||||
Platform_OpenInShellUserData = NULL;
|
||||
Platform_SetImeDataFn = NULL;
|
||||
Platform_ImeUserData = NULL;
|
||||
InitializeDefaultPlatformHandlers(*this); // Rrevents losing the functionality provided by Platform_*_DefaultImpl on backend re-creation.
|
||||
}
|
||||
|
||||
void ImGuiPlatformIO::ClearRendererHandlers()
|
||||
{
|
||||
Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0;
|
||||
Renderer_RenderState = NULL;
|
||||
DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = NULL;
|
||||
DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = DrawCallback_SetSamplerFromTex = NULL;
|
||||
}
|
||||
|
||||
ImGuiViewport* ImGui::GetMainViewport()
|
||||
@@ -16212,7 +16329,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* t
|
||||
::CloseClipboard();
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
|
||||
#elif defined(__APPLE__) && defined(TARGET_OS_OSX) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
|
||||
|
||||
#include <Carbon/Carbon.h> // Use old API to avoid need for separate .mm file
|
||||
static PasteboardRef main_clipboard = 0;
|
||||
@@ -16384,6 +16501,15 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImG
|
||||
|
||||
#endif // Default IME handlers
|
||||
|
||||
// Setup default ImGuiPlatformIO clipboard/IME handlers
|
||||
static void InitializeDefaultPlatformHandlers(ImGuiPlatformIO& platform_io)
|
||||
{
|
||||
platform_io.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl;
|
||||
platform_io.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
|
||||
platform_io.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
|
||||
platform_io.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] METRICS/DEBUGGER WINDOW
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -16611,7 +16737,7 @@ static const char* FormatTextureRefForDebugDisplay(char* buf, int buf_size, ImTe
|
||||
char* buf_end = buf + buf_size;
|
||||
if (tex_ref._TexData != NULL)
|
||||
buf_p += ImFormatString(buf_p, buf_end - buf_p, "#%03d: ", tex_ref._TexData->UniqueID);
|
||||
ImFormatString(buf_p, buf_end - buf_p, "0x%X", ImGui::DebugTextureIDToU64(tex_ref.GetTexID()));
|
||||
ImFormatString(buf_p, buf_end - buf_p, "0x%" IM_PRIX64, ImGui::DebugTextureIDToU64(tex_ref.GetTexID()));
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -16663,6 +16789,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
|
||||
if (TreeNode("Loader", "Loader: \'%s\'", atlas->FontLoaderName ? atlas->FontLoaderName : "NULL"))
|
||||
{
|
||||
const ImFontLoader* loader_current = atlas->FontLoader;
|
||||
IM_UNUSED(loader_current);
|
||||
BeginDisabled(!atlas->RendererHasTextures);
|
||||
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
||||
const ImFontLoader* loader_stbtruetype = ImFontAtlasGetFontLoaderForStbTruetype();
|
||||
@@ -16783,7 +16910,7 @@ void ImGui::DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRe
|
||||
Checkbox("Show used rect", &cfg->ShowTextureUsedRect);
|
||||
PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize));
|
||||
ImVec2 p = GetCursorScreenPos();
|
||||
if (tex->WantDestroyNextFrame)
|
||||
if (tex->Status == ImTextureStatus_WantDestroy || tex->Status == ImTextureStatus_Destroyed)
|
||||
Dummy(ImVec2((float)tex->Width, (float)tex->Height));
|
||||
else
|
||||
ImageWithBg(tex->GetTexRef(), ImVec2((float)tex->Width, (float)tex->Height), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
@@ -17585,10 +17712,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();
|
||||
@@ -17604,8 +17730,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
|
||||
@@ -17623,7 +17748,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.
|
||||
@@ -17633,7 +17758,8 @@ static int CalcFontGlyphSrcOverlapMask(ImFontAtlas* atlas, ImFont* font, unsigne
|
||||
for (int src_n = 0; src_n < font->Sources.Size; src_n++)
|
||||
{
|
||||
ImFontConfig* src = font->Sources[src_n];
|
||||
if (!(src->FontLoader ? src->FontLoader : atlas->FontLoader)->FontSrcContainsGlyph(atlas, src, (ImWchar)codepoint))
|
||||
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
|
||||
if (loader->FontSrcGetGlyphIndexFromCodepoint(atlas, src, (ImWchar)codepoint) == 0)
|
||||
continue;
|
||||
mask |= (1 << src_n);
|
||||
count++;
|
||||
@@ -18239,9 +18365,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)
|
||||
|
||||
Vendored
+398
-145
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (demo code)
|
||||
|
||||
// Help:
|
||||
@@ -87,6 +87,7 @@ Index of this file:
|
||||
// [SECTION] DemoWindowWidgetsImages()
|
||||
// [SECTION] DemoWindowWidgetsListBoxes()
|
||||
// [SECTION] DemoWindowWidgetsLiveEdit()
|
||||
// [SECTION] DemoWindowWidgetsMixedValues()
|
||||
// [SECTION] DemoWindowWidgetsMultiComponents()
|
||||
// [SECTION] DemoWindowWidgetsPlotting()
|
||||
// [SECTION] DemoWindowWidgetsProgressBars()
|
||||
@@ -575,6 +576,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).");
|
||||
|
||||
@@ -962,8 +965,9 @@ static void DemoWindowWidgetsBasic()
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
ImGui::Button("Click");
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleColor(4);
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
@@ -1258,6 +1262,7 @@ static void DemoWindowWidgetsColorAndPickers()
|
||||
ImGui::OpenPopup("mypicker");
|
||||
backup_color = color;
|
||||
}
|
||||
float ref_sz = ImGui::GetFrameHeight();
|
||||
if (ImGui::BeginPopup("mypicker"))
|
||||
{
|
||||
ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
|
||||
@@ -1265,11 +1270,12 @@ static void DemoWindowWidgetsColorAndPickers()
|
||||
ImGui::ColorPicker4("##picker", (float*)&color, base_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImVec2 color_button_sz(ref_sz * 3.0f, ref_sz * 2.0f);
|
||||
ImGui::BeginGroup(); // Lock X position
|
||||
ImGui::Text("Current");
|
||||
ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
|
||||
ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, color_button_sz);
|
||||
ImGui::Text("Previous");
|
||||
if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
|
||||
if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, color_button_sz))
|
||||
color = backup_color;
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Palette");
|
||||
@@ -1280,7 +1286,7 @@ static void DemoWindowWidgetsColorAndPickers()
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
|
||||
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
|
||||
if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
|
||||
if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags))
|
||||
color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
|
||||
|
||||
// Allow user to drop colors into each palette entry. Note that ColorButton() is already a
|
||||
@@ -1303,8 +1309,9 @@ static void DemoWindowWidgetsColorAndPickers()
|
||||
IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)");
|
||||
ImGui::Text("Color button only:");
|
||||
static bool no_border = false;
|
||||
const ImVec2 color_button_sz(ref_sz * 2.0f, ref_sz * 2.0f);
|
||||
ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
|
||||
ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, base_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
|
||||
ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, base_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), color_button_sz);
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
|
||||
ImGui::SeparatorText("Color picker");
|
||||
@@ -1451,7 +1458,8 @@ static void DemoWindowWidgetsComboBoxes()
|
||||
filter.Clear();
|
||||
}
|
||||
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F);
|
||||
filter.Draw("##Filter", -FLT_MIN);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
|
||||
|
||||
for (int n = 0; n < IM_COUNTOF(items); n++)
|
||||
{
|
||||
@@ -1678,12 +1686,13 @@ static void DemoWindowWidgetsDragAndDrop()
|
||||
"Brianna", "Barry", "Bernard",
|
||||
"Bibi", "Blaine", "Bryn"
|
||||
};
|
||||
float sz = ImGui::GetFrameHeight() * 3.0f;
|
||||
for (int n = 0; n < IM_COUNTOF(names); n++)
|
||||
{
|
||||
ImGui::PushID(n);
|
||||
if ((n % 3) != 0)
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(names[n], ImVec2(60, 60));
|
||||
ImGui::Button(names[n], ImVec2(sz, sz));
|
||||
|
||||
// Our buttons are both drag sources and drag targets here!
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
|
||||
@@ -2020,7 +2029,7 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
|
||||
{
|
||||
if (ImGui::TreeNode("Live Edit Flags"))
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Widgets/Live Edit Flgs");
|
||||
IMGUI_DEMO_MARKER("Widgets/Live Edit Flags");
|
||||
|
||||
ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing.");
|
||||
|
||||
@@ -2050,6 +2059,66 @@ static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsMixedValues()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void DemoWindowWidgetsMixedValues()
|
||||
{
|
||||
if (ImGui::TreeNode("Mixed Values"))
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Widgets/Mixed Values");
|
||||
// This is designed for advanced property editors which are generally reusable and data-driven.
|
||||
HelpMarker("Using ImGuiItemFlags_MixedValue.");
|
||||
|
||||
static bool use_liveedit = false;
|
||||
static float items[3] = { 12.0f, 0.0f, 0.0f };
|
||||
float* item_ref = &items[0];
|
||||
ImGui::Checkbox("ImGuiItemFlags_LiveEditOnInput", &use_liveedit);
|
||||
|
||||
ImGui::SeparatorText("Scalar/Text Widgets");
|
||||
const bool is_mixed = memcmp(&items[0], &items[1], sizeof(float)) != 0 || memcmp(&items[0], &items[2], sizeof(float)) != 0;
|
||||
|
||||
// Demonstrate Drags, Sliders, Inputs
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInput, use_liveedit);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, is_mixed);
|
||||
bool edited = false;
|
||||
edited |= ImGui::DragFloat("DragFloat", item_ref);
|
||||
edited |= ImGui::SliderFloat("SliderFloat", item_ref, 0.0f, 100.0f);
|
||||
edited |= ImGui::InputFloat("InputFloat", item_ref, 1.0f);
|
||||
if (edited)
|
||||
for (float& item : items)
|
||||
if (&item != item_ref)
|
||||
item = *item_ref;
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
ImGui::Text("Underlying data:");
|
||||
ImGui::InputFloat("item 0 (ref)", &items[0]);
|
||||
ImGui::InputFloat("item 1", &items[1]);
|
||||
ImGui::InputFloat("item 2", &items[2]);
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
// Demonstrate Checkbox(), RadioButton(), Combo(), ColorEdit4()
|
||||
ImGui::SeparatorText("Others Widgets");
|
||||
ImGui::Text("(note: edits are not applied in this demo)"); // <-- Would need more state tracking.
|
||||
bool b_on = true, b_off = false;
|
||||
ImGui::Checkbox("Checkbox On", &b_on);
|
||||
ImGui::Checkbox("Checkbox Off", &b_off);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
|
||||
ImGui::Checkbox("Checkbox Mixed", &b_off);
|
||||
ImGui::RadioButton("RadioButton Mixed", true);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("RadioButton Mixed##2", true); // Showing 2 radio buttons makes the example more clear
|
||||
int combo_idx = 0;
|
||||
ImGui::Combo("Combo", &combo_idx, "One\0Two\0Three\0");
|
||||
ImVec4 color(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
ImGui::ColorEdit4("ColorEdit4", &color.x);
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsMultiComponents()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2119,10 +2188,12 @@ static void DemoWindowWidgetsPlotting()
|
||||
static bool animate = true;
|
||||
ImGui::Checkbox("Animate", &animate);
|
||||
|
||||
ImVec2 plot_sz(0.0f, ImGui::GetFrameHeight() * 4.0f);
|
||||
|
||||
// Plot as lines and plot as histogram
|
||||
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
|
||||
ImGui::PlotLines("Frame Times", arr, IM_COUNTOF(arr));
|
||||
ImGui::PlotHistogram("Histogram", arr, IM_COUNTOF(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
|
||||
ImGui::PlotHistogram("Histogram", arr, IM_COUNTOF(arr), 0, NULL, 0.0f, 1.0f, plot_sz);
|
||||
//ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!");
|
||||
|
||||
// Fill an array of contiguous float values to plot
|
||||
@@ -2151,7 +2222,7 @@ static void DemoWindowWidgetsPlotting()
|
||||
average /= (float)IM_COUNTOF(values);
|
||||
char overlay[32];
|
||||
sprintf(overlay, "avg %f", average);
|
||||
ImGui::PlotLines("Lines", values, IM_COUNTOF(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
|
||||
ImGui::PlotLines("Lines", values, IM_COUNTOF(values), values_offset, overlay, -1.0f, 1.0f, plot_sz);
|
||||
}
|
||||
|
||||
// Use functions to generate output
|
||||
@@ -2169,8 +2240,8 @@ static void DemoWindowWidgetsPlotting()
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderInt("Sample count", &display_count, 1, 400);
|
||||
float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
|
||||
ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
|
||||
ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
|
||||
ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, plot_sz);
|
||||
ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, plot_sz);
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@@ -2230,12 +2301,14 @@ static void DemoWindowWidgetsQueryingStatuses()
|
||||
};
|
||||
static int item_type = 4;
|
||||
static bool item_disabled = false;
|
||||
static bool item_mixedvalue = false;
|
||||
static bool liveedit_flags_override = false;
|
||||
static ImGuiItemFlags liveedit_flags = 0;
|
||||
ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
|
||||
ImGui::SameLine();
|
||||
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
|
||||
ImGui::Checkbox("Item Disabled", &item_disabled);
|
||||
ImGui::Checkbox("Item MixedValue", &item_mixedvalue);
|
||||
ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override);
|
||||
ImGui::SameLine();
|
||||
if (!liveedit_flags_override)
|
||||
@@ -2260,6 +2333,8 @@ static void DemoWindowWidgetsQueryingStatuses()
|
||||
static char str[16] = {};
|
||||
if (item_disabled)
|
||||
ImGui::BeginDisabled(true);
|
||||
if (item_mixedvalue)
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
|
||||
if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
|
||||
if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
|
||||
if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
|
||||
@@ -2343,6 +2418,8 @@ static void DemoWindowWidgetsQueryingStatuses()
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopItemFlag();
|
||||
}
|
||||
if (item_mixedvalue)
|
||||
ImGui::PopItemFlag();
|
||||
if (item_disabled)
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -3678,11 +3755,13 @@ static void DemoWindowWidgetsTabs()
|
||||
// but they tend to make more sense together)
|
||||
static bool show_leading_button = true;
|
||||
static bool show_trailing_button = true;
|
||||
static bool show_leading_trailing_tabs = false;
|
||||
ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
|
||||
ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
|
||||
ImGui::Checkbox("Show Leading+Trailing TabItem()", &show_leading_trailing_tabs);
|
||||
|
||||
// Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
|
||||
static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyShrink;
|
||||
static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyMixed;
|
||||
EditTabBarFittingPolicyFlags(&tab_bar_flags);
|
||||
|
||||
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
|
||||
@@ -3697,6 +3776,15 @@ static void DemoWindowWidgetsTabs()
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Demo Leading/Trailing Tabs
|
||||
if (show_leading_trailing_tabs)
|
||||
{
|
||||
if (ImGui::BeginTabItem("Leading", NULL, ImGuiTabItemFlags_Leading))
|
||||
ImGui::EndTabItem();
|
||||
if (ImGui::BeginTabItem("Trailing", NULL, ImGuiTabItemFlags_Trailing))
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Demo Trailing Tabs: click the "+" button to add a new tab.
|
||||
// (In your app you may want to use a font icon instead of the "+")
|
||||
// We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
|
||||
@@ -3865,14 +3953,24 @@ static void DemoWindowWidgetsTextFilter()
|
||||
static ImGuiTextFilter filter;
|
||||
ImGui::Text("Filter usage:\n"
|
||||
" \"\" display all lines\n"
|
||||
" \"xxx\" display lines containing \"xxx\"\n"
|
||||
" \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
|
||||
" \"-xxx\" hide lines containing \"xxx\"");
|
||||
filter.Draw();
|
||||
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
|
||||
for (int i = 0; i < IM_COUNTOF(lines); i++)
|
||||
if (filter.PassFilter(lines[i]))
|
||||
ImGui::BulletText("%s", lines[i]);
|
||||
" xxx display lines containing \"xxx\"\n"
|
||||
" xxx yyy display lines containing \"xxx\" and \"yyy\"\n"
|
||||
" \"xxx yyy\" display lines containing \"xxx yyy\"\n"
|
||||
" xxx,yyy display lines containing \"xxx\" or \"yyy\"\n"
|
||||
" -xxx hide lines containing \"xxx\"");
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
|
||||
if (ImGui::BeginChild("##items", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 15), ImGuiChildFlags_FrameStyle))
|
||||
{
|
||||
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
|
||||
for (const char* item : lines)
|
||||
if (filter.PassFilter(item))
|
||||
ImGui::TextUnformatted(item);
|
||||
for (const char* item : ExampleNames)
|
||||
if (filter.PassFilter(item))
|
||||
ImGui::TextUnformatted(item);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -4402,27 +4500,34 @@ static void DemoWindowWidgetsVerticalSliders()
|
||||
if (ImGui::TreeNode("Vertical Sliders"))
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Widgets/Vertical Sliders");
|
||||
const float spacing = 4;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImVec2 slider_sz(ImGui::GetFrameHeight(), ImGui::GetFrameHeight() * 9);
|
||||
|
||||
ImGui::PushStyleVarX(ImGuiStyleVar_ItemSpacing, (float)(int)(style.ItemSpacing.x * 0.5f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, (float)(int)(slider_sz.x * 0.25f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_GrabRounding, (float)(int)(slider_sz.x * 0.25f));
|
||||
float spacing = style.ItemSpacing.x;
|
||||
|
||||
static int int_value = 0;
|
||||
ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
|
||||
ImGui::VSliderInt("##int", slider_sz, &int_value, 0, 5);
|
||||
ImGui::SameLine();
|
||||
|
||||
static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
|
||||
ImGui::PushID("set1");
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (i > 0) ImGui::SameLine();
|
||||
if (i > 0)ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
|
||||
ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
|
||||
ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.7f));
|
||||
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
|
||||
ImGui::VSliderFloat("##v", slider_sz, &values[i], 0.0f, 1.0f, "");
|
||||
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%.3f", values[i]);
|
||||
ImGui::PopStyleColor(4);
|
||||
ImGui::PopStyleColor(5);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopID();
|
||||
@@ -4431,15 +4536,15 @@ static void DemoWindowWidgetsVerticalSliders()
|
||||
ImGui::PushID("set2");
|
||||
static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
|
||||
const int rows = 3;
|
||||
const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
|
||||
const ImVec2 slider_size_small(slider_sz.x, (float)(int)((slider_sz.y - (rows - 1) * spacing) / rows));
|
||||
for (int nx = 0; nx < 4; nx++)
|
||||
{
|
||||
if (nx > 0) ImGui::SameLine();
|
||||
if (nx > 0)ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
for (int ny = 0; ny < rows; ny++)
|
||||
{
|
||||
ImGui::PushID(nx * rows + ny);
|
||||
ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
|
||||
ImGui::VSliderFloat("##v", slider_size_small, &values2[nx], 0.0f, 1.0f, "");
|
||||
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%.3f", values2[nx]);
|
||||
ImGui::PopID();
|
||||
@@ -4452,15 +4557,17 @@ static void DemoWindowWidgetsVerticalSliders()
|
||||
ImGui::PushID("set3");
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (i > 0) ImGui::SameLine();
|
||||
if (i > 0)
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
|
||||
ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, slider_sz.y * 0.25f);
|
||||
ImGui::VSliderFloat("##v", ImVec2(slider_sz.x * 2.0f, slider_sz.y), &values[i], 0.0f, 1.0f, "%.2f\nsec");
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -4505,6 +4612,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
|
||||
DemoWindowWidgetsImages();
|
||||
DemoWindowWidgetsListBoxes();
|
||||
DemoWindowWidgetsLiveEdit(demo_data);
|
||||
DemoWindowWidgetsMixedValues();
|
||||
DemoWindowWidgetsMultiComponents();
|
||||
DemoWindowWidgetsPlotting();
|
||||
DemoWindowWidgetsProgressBars();
|
||||
@@ -8072,7 +8180,8 @@ static void DemoWindowInputs()
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
|
||||
ImGui::SliderInt("SetNextFrameWantCaptureKeyboard() on hover", &capture_override_keyboard, -1, +1, capture_override_desc[capture_override_keyboard + 1], ImGuiSliderFlags_AlwaysClamp);
|
||||
|
||||
ImGui::ColorButton("##panel", ImVec4(0.7f, 0.1f, 0.7f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2(128.0f, 96.0f)); // Dummy item
|
||||
float ref_sz = ImGui::GetFrameHeight() * 4.0f;
|
||||
ImGui::ColorButton("##panel", ImVec4(0.7f, 0.1f, 0.7f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2(ref_sz, ref_sz)); // Dummy item
|
||||
if (ImGui::IsItemHovered() && capture_override_mouse != -1)
|
||||
ImGui::SetNextFrameWantCaptureMouse(capture_override_mouse == 1);
|
||||
if (ImGui::IsItemHovered() && capture_override_keyboard != -1)
|
||||
@@ -8742,9 +8851,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
SameLine(); SetNextItemWidth(GetFontSize() * 10); Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
|
||||
SameLine(); Checkbox("Only Modified Colors", &output_only_modified);
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw("Filter colors", GetFontSize() * 16);
|
||||
|
||||
static ImGuiColorEditFlags alpha_flags = 0;
|
||||
if (RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque)) { alpha_flags = ImGuiColorEditFlags_AlphaOpaque; } SameLine();
|
||||
if (RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } SameLine();
|
||||
@@ -8754,6 +8860,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
"Left-click on color square to open color picker,\n"
|
||||
"Right-click to open edit options menu.");
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
SetNextItemWidth(-FLT_MIN);
|
||||
filter.DrawWithHint("##FilterColors", "Filter Colors (incl -excl)");
|
||||
|
||||
SetNextWindowSizeConstraints(ImVec2(0.0f, GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX));
|
||||
BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
PushItemWidth(GetFontSize() * -12);
|
||||
@@ -8821,15 +8931,25 @@ 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 Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
|
||||
if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
|
||||
DragFloat("Curve Tessellation Max Error", &style.CurveTessellationMaxError, 0.02f, 0.10f, 10.0f, "%.2f");
|
||||
if (style.CurveTessellationMaxError < 0.10f)
|
||||
style.CurveTessellationMaxError = 0.10f;
|
||||
|
||||
// When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
|
||||
DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
|
||||
@@ -9165,7 +9285,10 @@ struct ExampleAppConsole
|
||||
if (ImGui::Button("Options"))
|
||||
ImGui::OpenPopup("Options");
|
||||
ImGui::SameLine();
|
||||
Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
|
||||
|
||||
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
Filter.DrawWithHint("##Filter", "Filter (incl -excl)");
|
||||
ImGui::Separator();
|
||||
|
||||
// Reserve enough left-over height for 1 separator + 1 input text
|
||||
@@ -9500,7 +9623,8 @@ struct ExampleAppLog
|
||||
ImGui::SameLine();
|
||||
bool copy = ImGui::Button("Copy");
|
||||
ImGui::SameLine();
|
||||
Filter.Draw("Filter", -100.0f);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
Filter.DrawWithHint("##Filter", "Filter (incl -excl)");
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -9695,7 +9819,7 @@ struct ExampleAppPropertyEditor
|
||||
ImGui::Text("(%d root nodes)", root_node->Childs.Size);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
|
||||
if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
|
||||
if (ImGui::InputTextWithHint("##Filter", "incl -excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
|
||||
Filter.Build();
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
@@ -10236,13 +10360,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)
|
||||
@@ -10274,118 +10395,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();
|
||||
@@ -10519,9 +10772,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();
|
||||
{
|
||||
@@ -10533,14 +10786,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();
|
||||
|
||||
Vendored
+2066
-531
File diff suppressed because it is too large.
Load diff
+24
-27
@@ -7,6 +7,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026/09/25: fixed handling of ExtraSizeScale.
|
||||
// 2025/06/11: refactored for the new ImFontLoader architecture, and ImGuiBackendFlags_RendererHasTextures support.
|
||||
// 2024/10/17: added plutosvg support for SVG Fonts (seems faster/better than lunasvg). Enable by using '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG'. (#7927)
|
||||
// 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
|
||||
@@ -220,17 +221,14 @@ void ImGui_ImplFreeType_FontSrcData::CloseFont()
|
||||
}
|
||||
}
|
||||
|
||||
static const FT_Glyph_Metrics* ImGui_ImplFreeType_LoadGlyph(ImGui_ImplFreeType_FontSrcData* src_data, uint32_t codepoint)
|
||||
static const FT_Glyph_Metrics* ImGui_ImplFreeType_LoadGlyph(ImGui_ImplFreeType_FontSrcData* src_data, uint32_t glyph_index)
|
||||
{
|
||||
uint32_t glyph_index = FT_Get_Char_Index(src_data->FtFace, codepoint);
|
||||
if (glyph_index == 0)
|
||||
return nullptr;
|
||||
|
||||
// If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
|
||||
// - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
|
||||
// - https://github.com/ocornut/imgui/issues/4567
|
||||
// - https://github.com/ocornut/imgui/issues/4566
|
||||
// You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
|
||||
IM_ASSERT(glyph_index != 0);
|
||||
FT_Error error = FT_Load_Glyph(src_data->FtFace, glyph_index, src_data->LoadFlags);
|
||||
if (error)
|
||||
return nullptr;
|
||||
@@ -416,17 +414,15 @@ static bool ImGui_ImplFreeType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* src
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas* atlas, ImFontConfig* src)
|
||||
static void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas*, ImFontConfig* src)
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
IM_DELETE(bd_font_data);
|
||||
src->FontLoaderData = nullptr;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
|
||||
static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas*, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
float size = baked->Size;
|
||||
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
|
||||
if (src->MergeMode && src->SizePixels != 0.0f)
|
||||
@@ -463,18 +459,19 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
|
||||
// Read metrics
|
||||
FT_Size_Metrics metrics = bd_baked_data->FtSize->metrics;
|
||||
const float scale = 1.0f / (rasterizer_density * src->ExtraSizeScale);
|
||||
baked->Ascent = (float)FT_CEIL(metrics.ascender) * scale; // The pixel extents above the baseline in pixels (typically positive).
|
||||
baked->Descent = (float)FT_CEIL(metrics.descender) * scale; // The extents below the baseline in pixels (typically negative).
|
||||
baked->Ascent = ((float)metrics.ascender / FT_SCALEFACTOR) * scale; // The pixel extents above the baseline in pixels (typically positive).
|
||||
baked->Descent = ((float)metrics.descender / FT_SCALEFACTOR) * scale; // The extents below the baseline in pixels (typically negative).
|
||||
//LineSpacing = (float)FT_CEIL(metrics.height) * scale; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate.
|
||||
//LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * scale; // The spacing in pixels between one row's descent and the next row's ascent.
|
||||
//MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * scale; // This field gives the maximum horizontal cursor advance for all glyphs in the font.
|
||||
baked->Ascent = ImRoundSigned64(baked->Ascent * rasterizer_density) / rasterizer_density;
|
||||
baked->Descent = ImRoundSigned64(baked->Descent * rasterizer_density) / rasterizer_density;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
|
||||
static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas*, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
IM_UNUSED(baked);
|
||||
IM_UNUSED(src);
|
||||
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = (ImGui_ImplFreeType_FontSrcBakedData*)loader_data_for_baked_src;
|
||||
@@ -483,13 +480,9 @@ static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontConfig
|
||||
bd_baked_data->~ImGui_ImplFreeType_FontSrcBakedData(); // ~IM_PLACEMENT_DELETE()
|
||||
}
|
||||
|
||||
static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x)
|
||||
static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x)
|
||||
{
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
uint32_t glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
|
||||
if (glyph_index == 0)
|
||||
return false;
|
||||
|
||||
if (bd_font_data->BakedLastActivated != baked) // <-- could use id
|
||||
{
|
||||
// Activate current size
|
||||
@@ -498,7 +491,7 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
|
||||
bd_font_data->BakedLastActivated = baked;
|
||||
}
|
||||
|
||||
const FT_Glyph_Metrics* metrics = ImGui_ImplFreeType_LoadGlyph(bd_font_data, codepoint);
|
||||
const FT_Glyph_Metrics* metrics = ImGui_ImplFreeType_LoadGlyph(bd_font_data, glyph_index);
|
||||
if (metrics == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -508,9 +501,9 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
|
||||
|
||||
// Load metrics only mode
|
||||
const float advance_x = (slot->advance.x / FT_SCALEFACTOR) / rasterizer_density;
|
||||
if (out_advance_x != NULL)
|
||||
if (out_advance_x != nullptr)
|
||||
{
|
||||
IM_ASSERT(out_glyph == NULL);
|
||||
IM_ASSERT(out_glyph == nullptr);
|
||||
*out_advance_x = advance_x;
|
||||
return true;
|
||||
}
|
||||
@@ -527,7 +520,6 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
|
||||
const bool is_visible = (w != 0 && h != 0);
|
||||
|
||||
// Prepare glyph
|
||||
out_glyph->Codepoint = codepoint;
|
||||
out_glyph->AdvanceX = advance_x;
|
||||
|
||||
// Pack and retrieve position inside texture atlas
|
||||
@@ -570,12 +562,16 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplFreetype_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint)
|
||||
static int ImGui_ImplFreetype_FontSrcGetGlyphIndexFromCodepoint(ImFontAtlas*, ImFontConfig* src, ImWchar codepoint)
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
int glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
|
||||
return glyph_index != 0;
|
||||
return (int)FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplFreeType_FontSrcContainsGlyph(ImFontAtlas*, ImFontConfig* src, int glyph_index)
|
||||
{
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
return glyph_index > 0 && glyph_index < bd_font_data->FtFace->num_glyphs;
|
||||
}
|
||||
|
||||
const ImFontLoader* ImGuiFreeType::GetFontLoader()
|
||||
@@ -586,7 +582,8 @@ const ImFontLoader* ImGuiFreeType::GetFontLoader()
|
||||
loader->LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
|
||||
loader->FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
|
||||
loader->FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
|
||||
loader->FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
|
||||
loader->FontSrcGetGlyphIndexFromCodepoint = ImGui_ImplFreetype_FontSrcGetGlyphIndexFromCodepoint;
|
||||
loader->FontSrcContainsGlyph = ImGui_ImplFreeType_FontSrcContainsGlyph;
|
||||
loader->FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
|
||||
loader->FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
|
||||
loader->FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;
|
||||
|
||||
Vendored
+20
-15
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@@ -375,7 +375,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
const int previous_frame_active = table->LastFrameActive;
|
||||
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
|
||||
const ImGuiTableFlags previous_flags = table->Flags;
|
||||
const bool is_new_table = (previous_frame_active == -1);
|
||||
table->ID = id;
|
||||
table->Flags = flags;
|
||||
table->LastFrameActive = g.FrameCount;
|
||||
@@ -384,6 +383,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->IsLayoutLocked = false;
|
||||
table->InnerWidth = inner_width;
|
||||
table->NavLayer = (ImS8)outer_window->DC.NavLayerCurrent;
|
||||
table->IsNewTable = (previous_frame_active == -1);
|
||||
temp_data->UserOuterSize = outer_size;
|
||||
|
||||
// Instance data (for instance 0, TableID == TableInstanceID)
|
||||
@@ -428,11 +428,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
SetNextWindowScroll(ImVec2(0.0f, 0.0f));
|
||||
|
||||
// Create scrolling region (without border and zero window padding)
|
||||
ImGuiChildFlags child_child_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : ImGuiChildFlags_None;
|
||||
ImGuiWindowFlags child_window_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) ? g.NextWindowData.WindowFlags : ImGuiWindowFlags_None;
|
||||
if (flags & ImGuiTableFlags_ScrollX)
|
||||
child_window_flags |= ImGuiWindowFlags_HorizontalScrollbar;
|
||||
BeginChildEx(name, instance_id, outer_rect.GetSize(), child_child_flags, child_window_flags);
|
||||
ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
|
||||
BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags);
|
||||
table->InnerWindow = g.CurrentWindow;
|
||||
table->WorkRect = table->InnerWindow->WorkRect;
|
||||
table->OuterRect = table->InnerWindow->Rect();
|
||||
@@ -588,7 +585,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
if (table->IsInitializing)
|
||||
{
|
||||
// Initialize
|
||||
if (is_new_table)
|
||||
if (table->IsNewTable)
|
||||
{
|
||||
table->SettingsOffset = -1;
|
||||
table->IsSettingsRequestLoad = true;
|
||||
@@ -634,7 +631,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
// At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn()
|
||||
if (table->ColumnsNames.Buf.Size > 0)
|
||||
table->ColumnsNames.Buf.resize(0);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1759,7 +1756,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
||||
ImGuiTableColumn* column = &table->Columns[column_idx];
|
||||
|
||||
// If topology change goes into reconcile mode
|
||||
if (table->IsReconcileMode == false && column->ID != column_id)
|
||||
if (table->IsReconcileMode == false && column->ID != column_id && !table->IsNewTable)
|
||||
{
|
||||
table->IsReconcileMode = true;
|
||||
table->TempData->ReconcileColumnsRequests.reserve(table->ColumnsCount - column_idx);
|
||||
@@ -2964,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)
|
||||
@@ -3021,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)
|
||||
{
|
||||
@@ -3032,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();
|
||||
@@ -3627,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();
|
||||
@@ -3973,7 +3972,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
||||
if (column->DisplayOrder != n)
|
||||
settings->SaveFlags |= ImGuiTableFlags_Reorderable;
|
||||
if (column->SortOrder != -1)
|
||||
settings->SaveFlags |= ImGuiTableFlags_Sortable;
|
||||
settings->SaveFlags |= ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable; // Because SortOrder saving itself is gated, make sure every column is saved (#9519)
|
||||
if (column->IsUserEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0))
|
||||
settings->SaveFlags |= ImGuiTableFlags_Hideable;
|
||||
}
|
||||
@@ -4110,6 +4109,12 @@ static int IMGUI_CDECL TableFixDisplayOrderComparer(const void* lhs, const void*
|
||||
// Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2)
|
||||
void ImGui::TableFixDisplayOrder(ImGuiTable* table)
|
||||
{
|
||||
if ((table->Flags & ImGuiTableFlags_Reorderable) == 0)
|
||||
{
|
||||
for (int n = 0; n < table->ColumnsCount; n++)
|
||||
table->DisplayOrderToIndex[n] = table->Columns[n].DisplayOrder = (ImGuiTableColumnIdx)n;
|
||||
return;
|
||||
}
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.TempBuffer.reserve((int)(sizeof(ImGuiTableFixDisplayOrderColumnData) * table->ColumnsCount)); // FIXME: Maybe wrap those two lines as a helper.
|
||||
ImGuiTableFixDisplayOrderColumnData* fdo_columns = (ImGuiTableFixDisplayOrderColumnData*)(void*)g.TempBuffer.Data;
|
||||
|
||||
Vendored
+277
-147
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.9b
|
||||
// dear imgui, v1.93.0
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -342,18 +342,18 @@ void ImGui::TextWrappedV(const char* fmt, va_list args)
|
||||
PopTextWrapPos();
|
||||
}
|
||||
|
||||
void ImGui::TextAligned(float align_x, float size_x, const char* fmt, ...)
|
||||
void ImGui::TextAligned(float align_x, float width, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextAlignedV(align_x, size_x, fmt, args);
|
||||
TextAlignedV(align_x, width, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// align_x: 0.0f = left, 0.5f = center, 1.0f = right.
|
||||
// size_x : 0.0f = shortcut for GetContentRegionAvail().x
|
||||
// FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||
void ImGui::TextAlignedV(float align_x, float size_x, const char* fmt, va_list args)
|
||||
// width < 0.0f (e.g. -FLT_MIN): shortcut for GetContentRegionAvail().x
|
||||
// FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024, #9455)
|
||||
void ImGui::TextAlignedV(float align_x, float width, const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
@@ -362,23 +362,25 @@ void ImGui::TextAlignedV(float align_x, float size_x, const char* fmt, va_list a
|
||||
const char* text, *text_end;
|
||||
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
|
||||
const ImVec2 text_size = CalcTextSize(text, text_end);
|
||||
size_x = CalcItemSize(ImVec2(size_x, 0.0f), 0.0f, text_size.y).x;
|
||||
|
||||
const ImVec2 size = CalcItemSize(ImVec2(width, 0.0f), 0.0f, text_size.y);
|
||||
ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
ImVec2 pos_max(pos.x + size_x, window->ClipRect.Max.y);
|
||||
ImVec2 size(ImMin(size_x, text_size.x), text_size.y);
|
||||
ImVec2 pos_max(pos.x + size.x, window->ClipRect.Max.y);
|
||||
|
||||
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, pos.x + text_size.x);
|
||||
window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, pos.x + text_size.x);
|
||||
if (align_x > 0.0f && text_size.x < size_x)
|
||||
pos.x += ImTrunc((size_x - text_size.x) * align_x);
|
||||
RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size);
|
||||
|
||||
const ImVec2 backup_max_pos = window->DC.CursorMaxPos;
|
||||
ItemSize(size);
|
||||
ItemAdd(ImRect(pos, pos + size), 0);
|
||||
window->DC.CursorMaxPos.x = backup_max_pos.x; // Cancel out extending content size because right-aligned text would otherwise mess it up.
|
||||
const bool is_visible = ItemAdd(ImRect(pos, pos + size), 0);
|
||||
window->DC.CursorMaxPos.x = backup_max_pos.x; // Cancel out extending content to 'size' to use 'text_size' allowing auto-resize to function with align_x > 0.0f
|
||||
if (!is_visible)
|
||||
return;
|
||||
|
||||
if (size_x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip))
|
||||
if (align_x > 0.0f && text_size.x < size.x)
|
||||
pos.x += ImTrunc((size.x - text_size.x) * align_x);
|
||||
RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size);
|
||||
|
||||
if (size.x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip))
|
||||
SetTooltip("%.*s", (int)(text_end - text), text);
|
||||
}
|
||||
|
||||
@@ -930,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);
|
||||
@@ -1396,7 +1398,7 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
RenderNavCursor(total_bb, id);
|
||||
const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
|
||||
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
|
||||
if (active)
|
||||
if (active && (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) == 0)
|
||||
{
|
||||
const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f));
|
||||
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
|
||||
@@ -1755,7 +1757,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
|
||||
@@ -1769,9 +1771,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);
|
||||
@@ -1781,7 +1783,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1949,7 +1951,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
const ImGuiID id = window->GetID(label);
|
||||
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
|
||||
if (flags & ImGuiComboFlags_WidthFitPreview)
|
||||
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);
|
||||
IM_ASSERT((flags & ImGuiComboFlags_NoPreview) == 0);
|
||||
|
||||
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
@@ -1978,24 +1980,19 @@ 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);
|
||||
}
|
||||
RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
|
||||
|
||||
// Custom preview
|
||||
if (flags & ImGuiComboFlags_CustomPreview)
|
||||
{
|
||||
g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
|
||||
IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
|
||||
preview_value = NULL;
|
||||
}
|
||||
// Store geometry for BeginComboPreview() - only necessary when visible.
|
||||
g.ComboPreviewData.PreviewRect = (flags & ImGuiComboFlags_NoPreview) ? ImRect() : ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
|
||||
|
||||
// Render preview and label
|
||||
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
|
||||
@@ -2077,6 +2074,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
|
||||
return false;
|
||||
}
|
||||
g.BeginComboDepth++;
|
||||
g.CurrentWindowStack.back().ParentLastComboPreviewRect = g.ComboPreviewData.PreviewRect;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2084,6 +2082,7 @@ void ImGui::EndCombo()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.BeginComboDepth--;
|
||||
g.ComboPreviewData.PreviewRect = g.CurrentWindowStack.back().ParentLastComboPreviewRect;
|
||||
char name[16];
|
||||
ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // FIXME: Move those to helpers?
|
||||
if (strcmp(g.CurrentWindow->Name, name) != 0)
|
||||
@@ -2091,19 +2090,26 @@ void ImGui::EndCombo()
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements
|
||||
// (Experimental, see GitHub issues: #1658, #4168)
|
||||
// Submit preview contents for BeginCombo()/EndCombo(), to display contents that's more than just a text label.
|
||||
// - [BETA] See GitHub issues: #1658, #4168.
|
||||
// - Make sure you call this after EndCombo().
|
||||
// - The preview is designed to only host non-interactive elements.
|
||||
// - Not compatible with ImGuiComboFlags_WidthFitPreview.
|
||||
// - 2026-09-08 (1.93.0): removed ImGuiComboFlags_CustomPreview. You can use BeginComboPreview()/EndComboPreview() without an extra flag.
|
||||
bool ImGui::BeginComboPreview()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
|
||||
|
||||
if (window->SkipItems || !(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible))
|
||||
return false;
|
||||
IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag?
|
||||
if (!window->ClipRect.Overlaps(preview_data->PreviewRect)) // Narrower test (optional)
|
||||
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
|
||||
if (!window->ClipRect.Overlaps(preview_data->PreviewRect) || preview_data->PreviewRect.GetWidth() <= 0.0f) // Narrower test (optional) + handle _NoPreview
|
||||
return false;
|
||||
IM_ASSERT_USER_ERROR_RETV(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y, false,
|
||||
"Call BeginComboPreview() after BeginCombo(), not after EndCombo()!"); // Calling after EndCombo() works only if you don't nest combos.
|
||||
IM_ASSERT_USER_ERROR_RETV(preview_data->WithinPreview == false, false,
|
||||
"Cannot recurse BeginComboPreview(): call EndComboPreview() before opening another combo.");
|
||||
|
||||
// FIXME: This could be contained in a PushWorkRect() api
|
||||
preview_data->BackupCursorPos = window->DC.CursorPos;
|
||||
@@ -2111,6 +2117,10 @@ bool ImGui::BeginComboPreview()
|
||||
preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
|
||||
preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
|
||||
preview_data->BackupLayout = window->DC.LayoutType;
|
||||
preview_data->WithinPreview = true;
|
||||
preview_data->BackupWorkRectMaxX = window->WorkRect.Max.x;
|
||||
preview_data->BackupContentRectMaxX = window->ContentRegionRect.Max.x;
|
||||
window->WorkRect.Max.x = window->ContentRegionRect.Max.x = preview_data->PreviewRect.Max.x - g.Style.FramePadding.x;
|
||||
window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;
|
||||
window->DC.CursorMaxPos = window->DC.CursorPos;
|
||||
window->DC.LayoutType = ImGuiLayoutType_Horizontal;
|
||||
@@ -2136,12 +2146,14 @@ void ImGui::EndComboPreview()
|
||||
}
|
||||
PopClipRect();
|
||||
window->DC.CursorPos = preview_data->BackupCursorPos;
|
||||
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos);
|
||||
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos); // No need to do the same with IdealMaxPos
|
||||
window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;
|
||||
window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;
|
||||
window->WorkRect.Max.x = preview_data->BackupWorkRectMaxX;
|
||||
window->ContentRegionRect.Max.x = preview_data->BackupContentRectMaxX;
|
||||
window->DC.LayoutType = preview_data->BackupLayout;
|
||||
window->DC.IsSameLine = false;
|
||||
preview_data->PreviewRect = ImRect();
|
||||
preview_data->WithinPreview = false;
|
||||
}
|
||||
|
||||
// Getter for the old Combo() API: const char*[]
|
||||
@@ -2174,7 +2186,9 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo
|
||||
|
||||
// Call the getter to obtain the preview string which is a parameter to BeginCombo()
|
||||
const char* preview_value = NULL;
|
||||
if (*current_item >= 0 && *current_item < items_count)
|
||||
if ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_MixedValue)
|
||||
preview_value = "";
|
||||
else if (*current_item >= 0 && *current_item < items_count)
|
||||
preview_value = getter(user_data, *current_item);
|
||||
|
||||
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
|
||||
@@ -2658,19 +2672,39 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ShortcutsForCancel(ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
bool is_cancel_with_keyboard = ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_None, id);
|
||||
bool is_cancel_with_gamepad = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0 && ImGui::Shortcut(ImGuiKey_NavGamepadCancel, ImGuiInputFlags_None, id);
|
||||
bool is_cancel_with_mouse = ImGui::IsMouseReleased(ImGuiMouseButton_Right, id);
|
||||
if (is_cancel_with_mouse)
|
||||
ImGui::SetKeyOwner(ImGuiKey_MouseRight, id);
|
||||
return is_cancel_with_keyboard || is_cancel_with_gamepad || is_cancel_with_mouse;
|
||||
}
|
||||
|
||||
bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
|
||||
{
|
||||
// Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
|
||||
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
|
||||
|
||||
// Things we can do easily outside the DragBehaviorT<> template, saves code generation.
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
// Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation.
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
|
||||
ClearActiveID();
|
||||
else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
|
||||
ClearActiveID();
|
||||
if (ShortcutsForCancel(id) && g.ActiveId == id) //-V560
|
||||
{
|
||||
// Canceling action reverts to initial value
|
||||
size_t data_size = DataTypeGetInfo(data_type)->Size;
|
||||
bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
|
||||
memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
|
||||
ClearActiveID();
|
||||
return value_changed;
|
||||
}
|
||||
}
|
||||
if (g.ActiveId != id)
|
||||
return false;
|
||||
@@ -2793,11 +2827,16 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
MarkItemEdited(id);
|
||||
|
||||
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
||||
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
char value_buf[64];
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("{", "}");
|
||||
if (is_mixed)
|
||||
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
if (is_mixed)
|
||||
PopStyleColor();
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
@@ -3004,7 +3043,7 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
|
||||
result = 0.0f; // Workaround for values that are in-range but below our fudge
|
||||
else if (v_clamped >= v_max_fudged)
|
||||
result = 1.0f; // Workaround for values that are in-range but above our fudge
|
||||
else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions
|
||||
else if (((FLOATTYPE)v_min * (FLOATTYPE)v_max) < 0.0f) // Range crosses zero, so split into two portions
|
||||
{
|
||||
float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine)
|
||||
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
|
||||
@@ -3058,7 +3097,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
|
||||
|
||||
float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range
|
||||
|
||||
if ((v_min * v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts
|
||||
if (((FLOATTYPE)v_min * (FLOATTYPE)v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts
|
||||
{
|
||||
float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space
|
||||
float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
|
||||
@@ -3083,13 +3122,13 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
|
||||
{
|
||||
result = ImLerp(v_min, v_max, t);
|
||||
}
|
||||
else if (t < 1.0)
|
||||
else // t is already < 1.0 here
|
||||
{
|
||||
// - For integer values we want the clicking position to match the grab box so we round above
|
||||
// This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
|
||||
// - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64
|
||||
// range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits.
|
||||
FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t;
|
||||
FLOATTYPE v_new_off_f = (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min) * (FLOATTYPE)t;
|
||||
result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5)));
|
||||
}
|
||||
}
|
||||
@@ -3138,37 +3177,24 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
float clicked_t = 0.0f;
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Mouse)
|
||||
{
|
||||
if (!g.IO.MouseDown[0])
|
||||
const float mouse_pos = g.IO.MousePos[axis];
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
ClearActiveID();
|
||||
}
|
||||
else
|
||||
{
|
||||
const float mouse_abs_pos = g.IO.MousePos[axis];
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||
if (axis == ImGuiAxis_Y)
|
||||
grab_t = 1.0f - grab_t;
|
||||
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
||||
const bool clicked_around_grab = (mouse_abs_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_abs_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here.
|
||||
g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_abs_pos - grab_pos : 0.0f;
|
||||
}
|
||||
if (slider_usable_sz > 0.0f)
|
||||
clicked_t = ImSaturate((mouse_abs_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz);
|
||||
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||
if (axis == ImGuiAxis_Y)
|
||||
clicked_t = 1.0f - clicked_t;
|
||||
set_new_value = true;
|
||||
grab_t = 1.0f - grab_t;
|
||||
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
|
||||
const bool clicked_around_grab = (mouse_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here.
|
||||
g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_pos - grab_pos : 0.0f;
|
||||
}
|
||||
if (slider_usable_sz > 0.0f)
|
||||
clicked_t = ImSaturate((mouse_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz);
|
||||
if (axis == ImGuiAxis_Y)
|
||||
clicked_t = 1.0f - clicked_t;
|
||||
set_new_value = true;
|
||||
}
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
||||
{
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation
|
||||
g.SliderCurrentAccumDirty = false;
|
||||
}
|
||||
|
||||
float input_delta = (axis == ImGuiAxis_X) ? GetNavTweakPressedAmount(axis) : -GetNavTweakPressedAmount(axis);
|
||||
if (input_delta != 0.0f)
|
||||
{
|
||||
@@ -3196,11 +3222,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
}
|
||||
|
||||
float delta = g.SliderCurrentAccum;
|
||||
if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
|
||||
{
|
||||
ClearActiveID();
|
||||
}
|
||||
else if (g.SliderCurrentAccumDirty)
|
||||
if (g.SliderCurrentAccumDirty)
|
||||
{
|
||||
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
|
||||
|
||||
@@ -3226,7 +3248,6 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
else
|
||||
g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta);
|
||||
}
|
||||
|
||||
g.SliderCurrentAccumDirty = false;
|
||||
}
|
||||
}
|
||||
@@ -3281,6 +3302,33 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
|
||||
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the legacy 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
|
||||
IM_ASSERT((flags & ImGuiSliderFlags_WrapAround) == 0); // Not supported by SliderXXX(), only by DragXXX()
|
||||
|
||||
// Things we can do easily outside the SliderBehaviorT<> template, saves code generation.
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
|
||||
ClearActiveID();
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
||||
{
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation
|
||||
g.SliderCurrentAccumDirty = false;
|
||||
}
|
||||
if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
|
||||
ClearActiveID();
|
||||
}
|
||||
if (ShortcutsForCancel(id) && g.ActiveId == id) //-V560
|
||||
{
|
||||
// Canceling action reverts to initial value
|
||||
size_t data_size = DataTypeGetInfo(data_type)->Size;
|
||||
bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
|
||||
memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
|
||||
ClearActiveID();
|
||||
return value_changed;
|
||||
}
|
||||
}
|
||||
|
||||
switch (data_type)
|
||||
{
|
||||
case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
|
||||
@@ -3391,11 +3439,16 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
|
||||
|
||||
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
||||
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
char value_buf[64];
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("{", "}");
|
||||
if (is_mixed)
|
||||
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
if (is_mixed)
|
||||
PopStyleColor();
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
@@ -3545,9 +3598,15 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
|
||||
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
||||
// For the vertical slider we allow centered text to overlap the frame padding
|
||||
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
char value_buf[64];
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, (is_mixed && g.MixedValueLabel != NULL) ? g.MixedValueLabel : format);
|
||||
if (is_mixed)
|
||||
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
|
||||
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
|
||||
if (is_mixed)
|
||||
PopStyleColor();
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
@@ -3633,6 +3692,7 @@ const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_
|
||||
const char* fmt_end = ImParseFormatFindEnd(fmt_start);
|
||||
if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
|
||||
return fmt_start;
|
||||
buf[0] = 0; // Fix false positive with caller assuming that buf could be non-initialized (#9508)
|
||||
ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size));
|
||||
return buf;
|
||||
}
|
||||
@@ -3784,6 +3844,10 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
|
||||
// Only mark as edited if new value is different
|
||||
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
|
||||
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue)
|
||||
if (ImGuiInputTextState* state = GetInputTextState(g.LastItemData.ID))
|
||||
value_changed |= (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (state->EditedThisFrame | state->ValidatedThisFrame) : state->ValidatedThisFrame;
|
||||
|
||||
if (value_changed)
|
||||
MarkItemEdited(id);
|
||||
return value_changed;
|
||||
@@ -3860,6 +3924,9 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
|
||||
}
|
||||
}
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue)
|
||||
if (ImGuiInputTextState* state = GetInputTextState(g.LastItemData.ID))
|
||||
value_changed |= (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (state->EditedThisFrame | state->ValidatedThisFrame) : state->ValidatedThisFrame;
|
||||
|
||||
// Step buttons
|
||||
if (has_step_buttons)
|
||||
@@ -4165,7 +4232,7 @@ static int STB_TEXTEDIT_MOVELINESTART_IMPL(ImGuiInputTextState* obj, ImStb::STB_
|
||||
const char* p_eol = ImFontCalcWordWrapPositionEx(g.Font, g.FontSize, p, text_end, obj->WrapWidth, ImDrawTextFlags_WrapKeepBlanks);
|
||||
if (p == p_cursor) // If we are already on a visible beginning-of-line, return real beginning-of-line (would be same as regular handler below)
|
||||
return (int)(p_bol - obj->TextSrc);
|
||||
if (p_eol == p_cursor && obj->TextA[cursor] != '\n' && obj->LastMoveDirectionLR == ImGuiDir_Left)
|
||||
if (p_eol == p_cursor && obj->TextSrc[cursor] != '\n' && obj->LastMoveDirectionLR == ImGuiDir_Left)
|
||||
return (int)(p_bol - obj->TextSrc);
|
||||
if (p_eol >= p_cursor)
|
||||
return (int)(p - obj->TextSrc);
|
||||
@@ -4728,7 +4795,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
IM_ASSERT(buf != NULL && buf_size >= 0);
|
||||
IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)
|
||||
IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
|
||||
IM_ASSERT(!((flags & ImGuiInputTextFlags_ElideLeft) && (flags & ImGuiInputTextFlags_Multiline))); // Multiline does not not work with left-trimming
|
||||
IM_ASSERT(!((flags & ImGuiInputTextFlags_ElideLeft) && (flags & ImGuiInputTextFlags_Multiline))); // Multiline does not work with left-trimming
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_WordWrap) == 0 || (flags & ImGuiInputTextFlags_Password) == 0); // WordWrap does not work with Password mode.
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_WordWrap) == 0 || (flags & ImGuiInputTextFlags_Multiline) != 0); // WordWrap does not work in single-line mode.
|
||||
|
||||
@@ -4825,6 +4892,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
||||
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
|
||||
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
if (is_resizable)
|
||||
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
|
||||
|
||||
@@ -4911,7 +4979,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
if (!is_multiline)
|
||||
{
|
||||
if (flags & ImGuiInputTextFlags_AutoSelectAll)
|
||||
if ((flags & ImGuiInputTextFlags_AutoSelectAll) || is_mixed)
|
||||
select_all = true;
|
||||
if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
|
||||
select_all = true;
|
||||
@@ -4989,7 +5057,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// Select the buffer to render.
|
||||
const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
|
||||
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
|
||||
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextSrc : buf)[0] == 0) && !is_mixed;
|
||||
|
||||
// Password pushes a temporary font with only a fallback glyph
|
||||
if (is_password && !is_displaying_hint)
|
||||
@@ -4998,6 +5066,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (state != NULL && state->ID == id)
|
||||
{
|
||||
state->Flags = flags;
|
||||
state->EditedThisFrame = state->ValidatedThisFrame = false;
|
||||
//state->LastFrameActive = g.FrameCount;
|
||||
|
||||
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset)
|
||||
@@ -5013,7 +5082,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
IM_ASSERT(state != NULL);
|
||||
state->EditedThisFrame = false;
|
||||
state->BufCapacity = buf_size;
|
||||
state->WrapWidth = wrap_width;
|
||||
|
||||
@@ -5215,7 +5283,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
if (flags & ImGuiInputTextFlags_EscapeClearsAll)
|
||||
{
|
||||
if (state->TextA.Data[0] != 0)
|
||||
if (state->TextSrc[0] != 0)
|
||||
{
|
||||
revert_edit = true;
|
||||
}
|
||||
@@ -5308,14 +5376,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (flags & ImGuiInputTextFlags_EscapeClearsAll)
|
||||
{
|
||||
// Clear input
|
||||
IM_ASSERT(state->TextA.Data[0] != 0);
|
||||
IM_ASSERT(state->TextSrc[0] != 0);
|
||||
apply_new_text = "";
|
||||
apply_new_text_length = 0;
|
||||
value_changed = true;
|
||||
char empty_string = 0;
|
||||
stb_textedit_replace(state, state->Stb, &empty_string, 0);
|
||||
}
|
||||
else if (strcmp(state->TextA.Data, state->TextToRevertTo.Data) != 0)
|
||||
else if (strcmp(state->TextSrc, state->TextToRevertTo.Data) != 0)
|
||||
{
|
||||
apply_new_text = state->TextToRevertTo.Data;
|
||||
apply_new_text_length = state->TextToRevertTo.Size - 1;
|
||||
@@ -5416,7 +5484,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText)
|
||||
{
|
||||
// Apply when modified
|
||||
if (strcmp(state->TextSrc, buf) != 0)
|
||||
if (strcmp(state->TextSrc, buf) != 0 || (is_mixed && (state->EditedThisFrame || validated)))
|
||||
{
|
||||
apply_new_text = state->TextSrc;
|
||||
apply_new_text_length = state->TextLen;
|
||||
@@ -5426,7 +5494,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
else
|
||||
{
|
||||
// Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert)
|
||||
value_changed = ((validated || clear_active_id || revert_edit) && strcmp(state->TextSrc, buf) != 0);
|
||||
value_changed = (validated || clear_active_id || revert_edit) && (strcmp(state->TextSrc, buf) != 0 || (is_mixed && validated));
|
||||
apply_new_text = value_changed ? state->TextSrc : NULL;
|
||||
apply_new_text_length = value_changed ? state->TextLen : 0;
|
||||
}
|
||||
@@ -5511,7 +5579,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// Display hint when contents is empty
|
||||
// At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368)
|
||||
const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
|
||||
const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
|
||||
if (new_is_displaying_hint != is_displaying_hint)
|
||||
{
|
||||
if (is_password && !is_displaying_hint)
|
||||
@@ -5520,10 +5588,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_password && !is_displaying_hint)
|
||||
PushPasswordFont();
|
||||
}
|
||||
if (is_displaying_hint)
|
||||
const bool is_displaying_mixed = is_mixed && g.ActiveId != id && apply_new_text == NULL;
|
||||
if (is_displaying_mixed && g.MixedValueLabel != NULL)
|
||||
{
|
||||
buf_display = g.MixedValueLabel;
|
||||
buf_display_end = buf_display + strlen(g.MixedValueLabel);
|
||||
render_cursor = render_selection = false;
|
||||
}
|
||||
else if (is_displaying_hint)
|
||||
{
|
||||
buf_display = hint;
|
||||
buf_display_end = hint + ImStrlen(hint);
|
||||
buf_display_end = buf_display + ImStrlen(buf_display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5563,7 +5638,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImVec2 draw_scroll;
|
||||
|
||||
// Render text. We currently only render selection when the widget is active or while scrolling.
|
||||
const ImU32 text_col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
|
||||
const ImU32 text_col = GetColorU32(is_displaying_mixed ? ImGuiCol_TextMixedValue : is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
|
||||
if (render_cursor || render_selection)
|
||||
{
|
||||
// Render text (with cursor and selection)
|
||||
@@ -5684,9 +5759,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.
|
||||
@@ -5736,6 +5811,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
if (state && validated)
|
||||
state->ValidatedThisFrame = true;
|
||||
if (value_changed)
|
||||
MarkItemEdited(id);
|
||||
|
||||
@@ -6012,7 +6089,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
|
||||
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
|
||||
SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
|
||||
PushItemFlag(ImGuiItemFlags_MixedValue, false);
|
||||
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
|
||||
PopItemFlag();
|
||||
}
|
||||
EndPopup();
|
||||
}
|
||||
@@ -6126,6 +6205,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
const bool is_readonly = ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
|
||||
g.NextItemData.ClearFlags();
|
||||
|
||||
const float backup_alpha = g.Style.Alpha;
|
||||
if (g.DisabledStackSize > 0)
|
||||
g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
|
||||
|
||||
PushID(label);
|
||||
const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0);
|
||||
if (set_current_color_edit_id)
|
||||
@@ -6283,6 +6366,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
if (!(flags & ImGuiColorEditFlags_NoSidePreview))
|
||||
{
|
||||
PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
|
||||
PushItemFlag(ImGuiItemFlags_MixedValue, false);
|
||||
ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
|
||||
if ((flags & ImGuiColorEditFlags_NoLabel))
|
||||
Text("Current");
|
||||
@@ -6300,6 +6384,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
}
|
||||
}
|
||||
PopItemFlag();
|
||||
PopItemFlag();
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
@@ -6465,7 +6550,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
{
|
||||
float alpha = ImSaturate(col[3]);
|
||||
ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
|
||||
RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
|
||||
RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), style.Alpha, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
|
||||
draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
|
||||
float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size);
|
||||
RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
|
||||
@@ -6483,6 +6568,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
g.ColorEditCurrentID = 0;
|
||||
PopID();
|
||||
|
||||
if (g.DisabledStackSize > 0)
|
||||
g.Style.Alpha = backup_alpha;
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -6515,34 +6603,42 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (flags & ImGuiColorEditFlags_InputHSV)
|
||||
ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
|
||||
|
||||
ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
|
||||
float grid_step = ImMin(size.x, size.y) / 2.99f;
|
||||
float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
|
||||
ImRect bb_inner = bb;
|
||||
float off = 0.0f;
|
||||
if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
|
||||
const ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
|
||||
const float grid_step = ImMin(size.x, size.y) / 2.99f;
|
||||
const float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
|
||||
const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
|
||||
const float backup_alpha = g.Style.Alpha;
|
||||
if (g.DisabledStackSize > 0)
|
||||
g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
|
||||
if (is_mixed)
|
||||
{
|
||||
off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts.
|
||||
bb_inner.Expand(off);
|
||||
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding);
|
||||
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextMixedValue]);
|
||||
if (g.MixedValueLabel != NULL)
|
||||
RenderTextClipped(ImVec2(bb.Min.x, bb.Min.y + g.Style.FramePadding.y), bb.Max, g.MixedValueLabel, NULL, NULL, ImVec2(0.5f, 0.0f));
|
||||
PopStyleColor();
|
||||
}
|
||||
if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
|
||||
else if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
|
||||
{
|
||||
float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f);
|
||||
float mid_x = IM_ROUND((bb.Min.x + bb.Max.x) * 0.5f);
|
||||
if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
|
||||
RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), 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_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundCornersRight);
|
||||
window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.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
|
||||
{
|
||||
// Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
|
||||
ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaOpaque) ? col_rgb_without_alpha : col_rgb;
|
||||
if (col_source.w < 1.0f && (flags & ImGuiColorEditFlags_AlphaNoBg) == 0)
|
||||
RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
|
||||
RenderColorRectWithAlphaCheckerboard(window->DrawList, bb.Min, bb.Max, ColorConvertFloat4ToU32(col_source), g.Style.Alpha, grid_step, ImVec2(0.0f, 0.0f), rounding);
|
||||
else
|
||||
window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
|
||||
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(col_source), rounding);
|
||||
}
|
||||
if (g.DisabledStackSize > 0)
|
||||
g.Style.Alpha = backup_alpha;
|
||||
RenderNavCursor(bb, id);
|
||||
if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
|
||||
{
|
||||
@@ -6560,7 +6656,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
|
||||
else
|
||||
SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
|
||||
PushItemFlag(ImGuiItemFlags_MixedValue, false);
|
||||
ColorButton(desc_id, col, flags);
|
||||
PopItemFlag();
|
||||
SameLine();
|
||||
TextEx("Color");
|
||||
EndDragDropSource();
|
||||
@@ -6604,7 +6702,9 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
|
||||
ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
|
||||
int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
|
||||
ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_;
|
||||
PushItemFlag(ImGuiItemFlags_MixedValue, false);
|
||||
ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz);
|
||||
PopItemFlag();
|
||||
SameLine();
|
||||
if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_))
|
||||
{
|
||||
@@ -6886,7 +6986,7 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
|
||||
}
|
||||
|
||||
// Store ImGuiTreeNodeStackData for just submitted node.
|
||||
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
|
||||
// Currently only supports 32 level deep. Easy to increase to e.g. 64.
|
||||
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -6909,6 +7009,9 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
|
||||
window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth);
|
||||
}
|
||||
|
||||
#define TREE_NODE_MAX_DEPTH 32
|
||||
#define TREE_NODE_GET_DEPTH_MASK(_DEPTH) (((ImU32)(_DEPTH) < TREE_NODE_MAX_DEPTH) ? (1u << (_DEPTH)) : 0u)
|
||||
|
||||
bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -6985,7 +7088,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0)
|
||||
flags |= g.Style.TreeLinesFlags;
|
||||
const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f);
|
||||
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen) && window->DC.TreeDepth < TREE_NODE_MAX_DEPTH)
|
||||
{
|
||||
store_tree_node_stack_data = draw_tree_lines;
|
||||
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsToParent) && !g.NavIdIsAlive)
|
||||
@@ -6996,12 +7099,16 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||
if (!is_visible)
|
||||
{
|
||||
if ((flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeRecordsClippedNodesY2Mask & (1 << (window->DC.TreeDepth - 1))))
|
||||
if (flags & ImGuiTreeNodeFlags_DrawLinesToNodes)
|
||||
{
|
||||
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
|
||||
if (frame_bb.Min.y >= window->ClipRect.Max.y)
|
||||
window->DC.TreeRecordsClippedNodesY2Mask &= ~(1 << (window->DC.TreeDepth - 1)); // Done
|
||||
const ImU32 tree_depth_mask = TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth - 1);
|
||||
if (window->DC.TreeRecordsClippedNodesY2Mask & tree_depth_mask)
|
||||
{
|
||||
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
|
||||
if (frame_bb.Min.y >= window->ClipRect.Max.y)
|
||||
window->DC.TreeRecordsClippedNodesY2Mask &= ~tree_depth_mask; // Done
|
||||
}
|
||||
}
|
||||
if (is_open && store_tree_node_stack_data)
|
||||
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
|
||||
@@ -7198,20 +7305,22 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (window->DC.TreeDepth == 0 || (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0)
|
||||
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));
|
||||
@@ -7219,7 +7328,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7242,10 +7354,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();
|
||||
}
|
||||
@@ -7282,8 +7396,7 @@ void ImGui::TreePop()
|
||||
Unindent();
|
||||
|
||||
window->DC.TreeDepth--;
|
||||
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
||||
|
||||
ImU32 tree_depth_mask = TREE_NODE_GET_DEPTH_MASK(window->DC.TreeDepth);
|
||||
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask)
|
||||
{
|
||||
const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||
@@ -7510,7 +7623,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
// - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
|
||||
// - (2) usage will fail with clipped items
|
||||
// The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
|
||||
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId)
|
||||
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId && !g.NavJustMovedToIsInit)
|
||||
if (g.NavJustMovedToId == id && (g.NavJustMovedToKeyMods & ImGuiMod_Ctrl) == 0)
|
||||
selected = pressed = auto_selected = true;
|
||||
}
|
||||
@@ -9031,7 +9144,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
|
||||
const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
|
||||
|
||||
// NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
|
||||
// We could render lower-level to save a bit of CPU.
|
||||
ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
|
||||
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
|
||||
if (plot_type == ImGuiPlotType_Lines)
|
||||
@@ -9042,6 +9155,8 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
{
|
||||
if (pos1.x >= pos0.x + 2.0f)
|
||||
pos1.x -= 1.0f;
|
||||
if (pos0.y > pos1.y)
|
||||
ImSwap(pos0.y, pos1.y);
|
||||
window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
|
||||
}
|
||||
|
||||
@@ -10114,16 +10229,17 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
}
|
||||
|
||||
// Horizontal scrolling buttons
|
||||
// Important: note that TabBarScrollButtons() will alter BarRect.Max.x.
|
||||
// - Important: note that TabBarScrollButtons() will alter BarRect.Max.x.
|
||||
// - Selection skips buttons and might cross through sections if there are Tabs in Leading/Trailing sections.
|
||||
const bool can_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) || (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyMixed);
|
||||
const float width_all_tabs_to_use_for_scroll = (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) ? tab_bar->WidthAllTabs : width_all_tabs_after_min_width_shrink;
|
||||
tab_bar->ScrollButtonEnabled = ((width_all_tabs_to_use_for_scroll > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && can_scroll);
|
||||
if (tab_bar->ScrollButtonEnabled)
|
||||
if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar))
|
||||
{
|
||||
scroll_to_tab_id = scroll_and_select_tab->ID;
|
||||
if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0)
|
||||
tab_bar->SelectedTabId = scroll_to_tab_id;
|
||||
tab_bar->SelectedTabId = scroll_and_select_tab->ID;
|
||||
scroll_to_tab_id = scroll_and_select_tab->ID;
|
||||
}
|
||||
if (scroll_to_tab_id == 0 && scroll_to_selected_tab)
|
||||
scroll_to_tab_id = tab_bar->SelectedTabId;
|
||||
@@ -10296,6 +10412,14 @@ const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
||||
return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
|
||||
}
|
||||
|
||||
ImVec2 ImGui::TabBarGetTabPos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
||||
{
|
||||
if ((tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0)
|
||||
return tab_bar->BarRect.Min + ImVec2(IM_TRUNC(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
|
||||
else
|
||||
return tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
|
||||
}
|
||||
|
||||
// The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
|
||||
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
||||
{
|
||||
@@ -10343,11 +10467,20 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
||||
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
// Clamp attempt to scroll to leading/trailing sections items.
|
||||
// This could be done at the TabBarScrollingButtons() call site as well, but here works.
|
||||
if (tab->Flags & ImGuiTabItemFlags_Leading)
|
||||
tab = &tab_bar->Tabs[sections[0].TabCount];
|
||||
else if (tab->Flags & ImGuiTabItemFlags_Trailing)
|
||||
tab = &tab_bar->Tabs[sections[0].TabCount + sections[1].TabCount];
|
||||
if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
|
||||
return;
|
||||
|
||||
// When scrolling to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
||||
// Disable the margin if the scrolling section is too small for the target tab: prefer displaying a maximum of the label.
|
||||
ImGuiContext& g = *GImGui;
|
||||
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
||||
float margin = ImClamp(tab_bar->ScrollingRectMaxX - tab_bar->ScrollingRectMinX - tab->Width, g.Style.ItemInnerSpacing.x, g.FontSize * 1.0f);
|
||||
int order = TabBarGetTabOrder(tab_bar, tab);
|
||||
|
||||
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
||||
@@ -10749,10 +10882,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// Layout
|
||||
const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
|
||||
size.x = tab->Width;
|
||||
if (is_central_section)
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_TRUNC(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
|
||||
else
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
|
||||
window->DC.CursorPos = TabBarGetTabPos(tab_bar, tab);
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
ImRect bb(pos, pos + size);
|
||||
|
||||
@@ -10823,8 +10953,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)
|
||||
{
|
||||
@@ -10835,7 +10965,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);
|
||||
@@ -10924,14 +11054,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?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3317,9 +3317,8 @@ void Achievements::DrawLeaderboardsWindow()
|
||||
|
||||
const float line_thickness = LayoutScale(1.0f);
|
||||
const float line_padding = LayoutScale(5.0f);
|
||||
const ImVec2 line_start(bb.Min.x, bb.Min.y + GetLineHeight(g_large_font) + line_padding);
|
||||
const ImVec2 line_end(bb.Max.x, line_start.y);
|
||||
ImGui::GetWindowDrawList()->AddLine(line_start, line_end, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
const float line_y = bb.Min.y + GetLineHeight(g_large_font) + line_padding;
|
||||
ImGui::GetWindowDrawList()->AddLineH(bb.Min.x, bb.Max.x, line_y, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,11 +1205,10 @@ void ImGuiFullscreen::DrawWindowTitle(const char* title)
|
||||
RenderTextClippedWithShadow(rect.Min, rect.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &rect);
|
||||
ImGui::PopFont();
|
||||
|
||||
const ImVec2 line_start(pos.x, pos.y + g_large_font.second + LayoutScale(LAYOUT_MENU_BUTTON_Y_PADDING));
|
||||
const ImVec2 line_end(pos.x + size.x, line_start.y);
|
||||
const float line_y = pos.y + g_large_font.second + LayoutScale(LAYOUT_MENU_BUTTON_Y_PADDING);
|
||||
const float line_thickness = LayoutScale(1.0f);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
dl->AddLine(line_start, line_end, IM_COL32(255, 255, 255, 255), line_thickness);
|
||||
dl->AddLineH(pos.x, pos.x + size.x, line_y, IM_COL32(255, 255, 255, 255), line_thickness);
|
||||
}
|
||||
|
||||
void ImGuiFullscreen::GetMenuButtonFrameBounds(float height, ImVec2* pos, ImVec2* size)
|
||||
@@ -1363,9 +1362,8 @@ void ImGuiFullscreen::MenuHeading(const char* title, bool draw_line /*= true*/)
|
||||
|
||||
if (draw_line)
|
||||
{
|
||||
const ImVec2 line_start(bb.Min.x, bb.Min.y + g_large_font.second + line_padding);
|
||||
const ImVec2 line_end(bb.Max.x, line_start.y);
|
||||
ImGui::GetWindowDrawList()->AddLine(line_start, line_end, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
const float line_y = bb.Min.y + g_large_font.second + line_padding;
|
||||
ImGui::GetWindowDrawList()->AddLineH(bb.Min.x, bb.Max.x, line_y, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1399,9 +1397,8 @@ bool ImGuiFullscreen::MenuHeadingButton(
|
||||
|
||||
if (draw_line)
|
||||
{
|
||||
const ImVec2 line_start(bb.Min.x, bb.Min.y + g_large_font.second + line_padding);
|
||||
const ImVec2 line_end(bb.Max.x, line_start.y);
|
||||
ImGui::GetWindowDrawList()->AddLine(line_start, line_end, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
const float line_y = bb.Min.y + g_large_font.second + line_padding;
|
||||
ImGui::GetWindowDrawList()->AddLineH(bb.Min.x, bb.Max.x, line_y, ImGui::GetColorU32(ImGuiCol_TextDisabled), line_thickness);
|
||||
}
|
||||
|
||||
return pressed;
|
||||
@@ -3239,9 +3236,9 @@ void ImGuiFullscreen::DrawNotifications(ImVec2& position, float spacing)
|
||||
ImDrawList* dl = ImGui::GetForegroundDrawList();
|
||||
dl->AddRectFilled(ImVec2(box_min.x + shadow_size, box_min.y + shadow_size),
|
||||
ImVec2(box_max.x + shadow_size, box_max.y + shadow_size),
|
||||
IM_COL32(20, 20, 20, (180 * opacity) / 255u), rounding, ImDrawFlags_RoundCornersAll);
|
||||
dl->AddRectFilled(box_min, box_max, background_color, rounding, ImDrawFlags_RoundCornersAll);
|
||||
dl->AddRect(box_min, box_max, border_color, rounding, ImGuiFullscreen::LayoutScale(1.0f), ImDrawFlags_RoundCornersAll);
|
||||
IM_COL32(20, 20, 20, (180 * opacity) / 255u), rounding, ImDrawFlags_RoundAll);
|
||||
dl->AddRectFilled(box_min, box_max, background_color, rounding, ImDrawFlags_RoundAll);
|
||||
dl->AddRect(box_min, box_max, border_color, rounding, ImGuiFullscreen::LayoutScale(1.0f), ImDrawFlags_RoundAll);
|
||||
|
||||
if (has_badge)
|
||||
{
|
||||
|
||||
@@ -702,13 +702,13 @@ bool ImGuiManager::AddEmojiFont()
|
||||
// See https://github.com/ocornut/imgui/issues/8240
|
||||
static ImFontLoader filter_loader;
|
||||
filter_loader.Name = "Emoji Preprocessor";
|
||||
filter_loader.FontSrcContainsGlyph = [](ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint) {
|
||||
filter_loader.FontSrcGetGlyphIndexFromCodepoint = [](ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint) -> int {
|
||||
if (codepoint == 0xfe0e || codepoint == 0xfe0f)
|
||||
return true;
|
||||
return false;
|
||||
return static_cast<int>(codepoint);
|
||||
return 0;
|
||||
};
|
||||
filter_loader.FontBakedLoadGlyph = [](ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x) {
|
||||
if (codepoint != 0xfe0e && codepoint != 0xfe0f)
|
||||
filter_loader.FontBakedLoadGlyph = [](ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x) {
|
||||
if (glyph_index != 0xfe0e && glyph_index != 0xfe0f)
|
||||
return false;
|
||||
|
||||
// Metrics only mode
|
||||
@@ -718,7 +718,6 @@ bool ImGuiManager::AddEmojiFont()
|
||||
return true;
|
||||
}
|
||||
|
||||
out_glyph->Codepoint = codepoint;
|
||||
out_glyph->AdvanceX = 0.0f;
|
||||
out_glyph->Visible = false;
|
||||
|
||||
|
||||
@@ -719,7 +719,7 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
|
||||
const float grid_y = plot_br.y - frac * graph_size.y;
|
||||
const float ly = grid_y - font_size * 0.5f;
|
||||
|
||||
dl->AddLine(ImVec2(plot_tl.x, grid_y), ImVec2(plot_br.x, grid_y), IM_COL32(255, 255, 255, 40), 1.0f);
|
||||
dl->AddLineH(plot_tl.x, plot_br.x, grid_y, IM_COL32(255, 255, 255, 40), 1.0f);
|
||||
|
||||
s.format("{:.1f}", min_val + (max_val - min_val) * frac);
|
||||
const float left_text_w = osd_font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, s.c_str(), s.c_str() + s.length()).x;
|
||||
|
||||
Reference in new issue
Block a user